[Git][ghc/ghc][wip/jeltsch/improve-closure-property-check] Remove erroneous GHC flag in `hadrian-multi`
by Wolfgang Jeltsch (@jeltsch) 24 Sep '26
by Wolfgang Jeltsch (@jeltsch) 24 Sep '26
24 Sep '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/improve-closure-property-check at Glasgow Haskell Compiler / GHC
Commits:
c3a50a05 by Wolfgang Jeltsch at 2026-09-24T12:13:31+03:00
Remove erroneous GHC flag in `hadrian-multi`
The flag was `-Werror=-Wno-error=incomplete-record-selectors`. Its
purpose was to permit incomplete record selectors, but because of the
illegal combination of `-Werror=` and `-Wno-error` it was ignored,
without any negative consequences.
- - - - -
1 changed file:
- .gitlab-ci.yml
Changes:
=====================================
.gitlab-ci.yml
=====================================
@@ -497,12 +497,7 @@ hadrian-multi:
# workaround for docker permissions
- sudo chown ghc:ghc -R .
variables:
- GHC_FLAGS: "-Werror=-Wno-error=incomplete-record-selectors -Wwarn=deprecations -Wwarn=unused-imports"
- # -Wno-error=incomplete-record-selectors is present because -Wall now
- # includes -Wincomplete-record-selectors, and hadrian-multi has many, many
- # warnings about incomplete record selectors. A better fix would be to
- # remove the use of incomplete record selectors, since each of them represents
- # a potential crash.
+ GHC_FLAGS: "-Wwarn=deprecations -Wwarn=unused-imports"
CONFIGURE_ARGS: --enable-bootstrap-with-devel-snapshot
tags:
- x86_64-linux
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c3a50a05a34de16cea00905643b7517…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c3a50a05a34de16cea00905643b7517…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/T27737] Eliminate accidental pprTrace
by Simon Peyton Jones (@simonpj) 24 Sep '26
by Simon Peyton Jones (@simonpj) 24 Sep '26
24 Sep '26
Simon Peyton Jones pushed to branch wip/T27737 at Glasgow Haskell Compiler / GHC
Commits:
66202905 by Simon Peyton Jones at 2026-09-24T08:57:07+01:00
Eliminate accidental pprTrace
- - - - -
1 changed file:
- compiler/GHC/Core/Opt/Simplify/Utils.hs
Changes:
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -646,7 +646,7 @@ splitContArgs cont@(CastIt { sc_cont = cont1 })
; return (cont { sc_cont = inner }, outer) }
splitContArgs outer
| contIsStop outer = Nothing
- | otherwise = pprTrace "splitContHoleType" (ppr hole_ty) $
+ | otherwise = -- pprTrace "splitContHoleType" (ppr hole_ty) $
return (mkBoringStop hole_ty, outer)
where
hole_ty = contHoleType outer
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6620290577236cf5dbc2a2f7f0d0abd…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6620290577236cf5dbc2a2f7f0d0abd…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
Simon Peyton Jones pushed to branch wip/T27737 at Glasgow Haskell Compiler / GHC
Commits:
eac53361 by Simon Peyton Jones at 2026-09-23T23:56:52+01:00
Wibbles
- - - - -
3 changed files:
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- testsuite/tests/simplCore/should_compile/T26903.stderr
Changes:
=====================================
compiler/GHC/Core/Opt/Simplify/Iteration.hs
=====================================
@@ -1339,15 +1339,11 @@ simplExprF1 env (Let (Rec pairs) body) cont
splitContForNoCaseCase :: SimplEnv -> SimplCont
-> Maybe (SimplCont, SimplCont)
--- Splits `cont` into (inner, outer), where `inner` has only
--- applications, and `outer` is non-trivial
+-- When seCaseCase is off, this function splits `cont` into (inner, outer),
+-- where `inner` has only applications, and `outer` is non-trivial
splitContForNoCaseCase env cont
- | not (seCaseCase env)
- , (inner, outer) <- splitContArgs cont
- , not (contIsStop outer)
- = Just (inner, outer)
- | otherwise
- = Nothing
+ | seCaseCase env = Nothing
+ | otherwise = splitContArgs cont
{- Note [Avoiding space leaks in OutType]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -632,17 +632,24 @@ contOutArgs env cont
-- No more arguments
go _ = []
-splitContArgs :: SimplCont -> (SimplCont, SimplCont)
--- Peel off an initial prefix of applications and casts
+splitContArgs :: SimplCont -> Maybe (SimplCont, SimplCont)
+-- Splits `cont` into (inner, outer), where `inner` has only
+-- applications and casts, and `outer` is non-trivial
splitContArgs cont@(ApplyToTy { sc_cont = cont1 })
- | (inner, outer) <- splitContArgs cont1 = (cont { sc_cont = inner }, outer)
+ = do { (inner, outer) <- splitContArgs cont1
+ ; return (cont { sc_cont = inner }, outer) }
splitContArgs cont@(ApplyToVal { sc_cont = cont1 })
- | (inner, outer) <- splitContArgs cont1 = (cont { sc_cont = inner }, outer)
+ = do { (inner, outer) <- splitContArgs cont1
+ ; return (cont { sc_cont = inner }, outer) }
splitContArgs cont@(CastIt { sc_cont = cont1 })
- | (inner, outer) <- splitContArgs cont1 = (cont { sc_cont = inner }, outer)
-splitContArgs cont
- | contIsStop cont = (cont, cont)
- | otherwise = (mkBoringStop (contHoleType cont), cont)
+ = do { (inner, outer) <- splitContArgs cont1
+ ; return (cont { sc_cont = inner }, outer) }
+splitContArgs outer
+ | contIsStop outer = Nothing
+ | otherwise = pprTrace "splitContHoleType" (ppr hole_ty) $
+ return (mkBoringStop hole_ty, outer)
+ where
+ hole_ty = contHoleType outer
dropContArgs :: FullArgCount -> SimplCont -> SimplCont
dropContArgs 0 cont = cont
=====================================
testsuite/tests/simplCore/should_compile/T26903.stderr
=====================================
@@ -1,35 +1,42 @@
==================== Tidy Core ====================
Result size of Tidy Core
- = {terms: 127, types: 130, coercions: 48, joins: 0/0}
+ = {terms: 127, types: 130, coercions: 24, joins: 0/0}
$dmop
- = (\ @a _ $dOrd xs ys ->
- case $fOrdList_$ccompare $dOrd xs ys of {
- __DEFAULT ->
- reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [];
- GT -> reverse1 (reverse1 (reverse1 (reverse xs) []) []) []
- })
- `cast` <Co:20> :: ...
+ = \ @a $dC $dOrd xs ys ->
+ case $fOrdList_$ccompare $dOrd xs ys of {
+ __DEFAULT ->
+ (reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [])
+ `cast` <Co:3>;
+ GT ->
+ (reverse1 (reverse1 (reverse1 (reverse xs) []) []) [])
+ `cast` <Co:3>
+ }
$fCInt_$cop
- = (\ xs ys ->
- case $fOrdList_$s$ccompare xs ys of {
- __DEFAULT ->
- reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [];
- GT -> reverse1 (reverse1 (reverse1 (reverse xs) []) []) []
- })
- `cast` <Co:11> :: ...
+ = \ xs ys ->
+ case $fOrdList_$s$ccompare xs ys of {
+ __DEFAULT ->
+ (reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [])
+ `cast` <Co:3>;
+ GT ->
+ (reverse1 (reverse1 (reverse1 (reverse xs) []) []) [])
+ `cast` <Co:3>
+ }
$fCInt1
= \ xs ys ->
case $fOrdList_$s$ccompare xs ys of {
__DEFAULT ->
- reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [];
- GT -> reverse1 (reverse1 (reverse1 (reverse xs) []) []) []
+ (reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [])
+ `cast` <Co:3>;
+ GT ->
+ (reverse1 (reverse1 (reverse1 (reverse xs) []) []) [])
+ `cast` <Co:3>
}
-$fCInt = C:C ($fCInt1 `cast` <Co:11> :: ...)
+$fCInt = C:C $fCInt1
test4 = reverse1 [] []
@@ -44,8 +51,8 @@ test
case $fOrdList_$s$ccompare [] xs of {
__DEFAULT ->
(reverse1 (reverse1 (reverse1 (reverse1 (++ [] xs) []) []) []) [])
- `cast` <Co:3> :: ...;
- GT -> test1 `cast` <Co:3> :: ...
+ `cast` <Co:3>;
+ GT -> test1 `cast` <Co:3>
}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/eac53361f27c482cfdb34ca51f64f53…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/eac53361f27c482cfdb34ca51f64f53…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/apk/expose-overloaded-unfoldings] Enable -fexpose-overloaded-unfoldings by default when optimizations are on.
by Andreas Klebinger (@AndreasK) 23 Sep '26
by Andreas Klebinger (@AndreasK) 23 Sep '26
23 Sep '26
Andreas Klebinger pushed to branch wip/apk/expose-overloaded-unfoldings at Glasgow Haskell Compiler / GHC
Commits:
2a7bffed by Andreas Klebinger at 2026-09-24T00:52:02+02:00
Enable -fexpose-overloaded-unfoldings by default when optimizations are on.
I also made the -fexpose-*-unfoldings flags optimization flags rather
than codeGen flags. This was needed to fix a test and is the correct
place for them.
Performance numbers:
In general this averages out to ~1% more file size across the GHC build.
Compiler allocations grow by 0.14% on nofib as the compiler needs to deal with more available unfoldings.
On the cabal test it's awash. With some configurations getting slightly faster, some slightly slower.
It's all in the +/- 0.2% range.
On nofib itself we produce exactly the same code. Which is expected, as it doesn't use -fspecialize-aggresively
anywhere afaik which is needed to take advantage of cross module
specialization.
Fixes #13090
-------------------------
Metric Increase:
LinkableUsage01
LinkableUsage02
hard_hole_fits
-------------------------
- - - - -
6 changed files:
- + changelog.d/T13090-expose-overloaded-unfoldings
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Iface/Tidy.hs
- docs/users_guide/using-optimisation.rst
- testsuite/tests/dmdanal/should_compile/T23398.stderr
Changes:
=====================================
changelog.d/T13090-expose-overloaded-unfoldings
=====================================
@@ -0,0 +1,6 @@
+section: compiler
+issues: #13090
+mrs: !16684
+synopsis:
+ Enable :ghc-flag:`-fexpose-overloaded-unfoldings` by default with :ghc-flag:`-O` or higher.
+
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -1337,6 +1337,7 @@ optLevelFlags -- see Note [Documenting optimisation flags]
, ([1,2], Opt_Specialise)
, ([1,2], Opt_PolymorphicSpecialisation) -- Now on by default (#23559)
, ([1,2], Opt_CrossModuleSpecialise)
+ , ([1,2], Opt_ExposeOverloadedUnfoldings) -- See Note [Exposing overloaded functions] in GHC.Iface.Tidy
, ([1,2], Opt_InlineGenerics)
, ([1,2], Opt_Strictness)
, ([1,2], Opt_UnboxSmallStrictFields)
=====================================
compiler/GHC/Driver/Flags.hs
=====================================
@@ -971,6 +971,8 @@ optimisationFlags = EnumSet.fromList
, Opt_SolveConstantDicts
, Opt_SpecEval
, Opt_SpecEvalDictFun
+ , Opt_ExposeAllUnfoldings
+ , Opt_ExposeOverloadedUnfoldings
]
-- | The set of flags which affect code generation and can change a program's
@@ -1001,8 +1003,6 @@ codeGenFlags = EnumSet.fromList
, Opt_OmitYields
-- Flags that affect generated code
- , Opt_ExposeAllUnfoldings
- , Opt_ExposeOverloadedUnfoldings
, Opt_NoTypeableBinds
, Opt_NoBuiltinRules
, Opt_NoBignumRules
=====================================
compiler/GHC/Iface/Tidy.hs
=====================================
@@ -806,8 +806,19 @@ anyway we allow for some false positives and simply expose all functions which
have a constraint. This means we might expose more unhelpful unfoldings. But
it seems like the better choice.
-Currently this option is off by default and has to be enabled manually. But
-we might change this in the future.
+We enable the flag by default with -O/O2 to allow users to opt into specialization
+at call sites. We do not enable -fspecialize-aggressively. See also #13090.
+
+In terms of performance impact the cost is very modest:
+On GHC and it's boot libraries overall enabling this flag increases overall disk
+space used by ~1%. With a highly variant distribution across various .hi files.
+In terms of compile times the overhead is low enough to be hard to measure, but
+seemed to be less than 0.2% if anything at all.
+
+It seems tempting to do the same for -fspecialize-aggressively, but that comes in
+at a hefty 20% compile time overhead. So we only provide the unfoldings and leave
+the choice of how much specialization to enable up to the user.
+
-}
{-
=====================================
docs/users_guide/using-optimisation.rst
=====================================
@@ -624,10 +624,10 @@ as such you shouldn't need to set any of them explicitly. A flag
:reverse: -fno-expose-overloaded-unfoldings
:category:
- :default: off
+ :default: -O and above
:since: 9.12.1
- This experimental flag is a slightly less heavy weight alternative
+ This flag is a slightly less heavy weight alternative
to :ghc-flag:`-fexpose-all-unfoldings`.
Instead of exposing all functions it exposes only those functions which
=====================================
testsuite/tests/dmdanal/should_compile/T23398.stderr
=====================================
@@ -40,7 +40,9 @@ T23398.$wbar [InlPrag=[2], Occ=LoopBreaker]
[GblId[StrictWorker([~, !])],
Arity=4,
Str=<L><SP(A,SC(S,L),A)><1L><L>,
- Unf=OtherCon []]
+ Unf=Unf{Src=<vanilla>, TopLvl=True,
+ Value=True, ConLike=True, WorkFree=True, Expandable=True,
+ Guidance=IF_ARGS [0 90 60 0] 91 70}]
T23398.$wbar
= \ (@a)
(@b)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2a7bffed1afac184dbff4ee986615c4…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2a7bffed1afac184dbff4ee986615c4…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/jeltsch/improve-closure-property-check] 2 commits: Improve the definition of the home unit closure property
by Wolfgang Jeltsch (@jeltsch) 23 Sep '26
by Wolfgang Jeltsch (@jeltsch) 23 Sep '26
23 Sep '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/improve-closure-property-check at Glasgow Haskell Compiler / GHC
Commits:
b8a1b2fc by Wolfgang Jeltsch at 2026-09-24T00:07:53+03:00
Improve the definition of the home unit closure property
- - - - -
428b90b7 by Wolfgang Jeltsch at 2026-09-24T00:54:52+03:00
Re-implement the home unit closure check
Compared to the previous implementation, the new one has the following
advantages:
* It is correct.
- It distinguishes between units that have the same unit ID but
different ABI hashes.
- When `-hide-all-packages` is not used, it considers as home unit
dependencies also units that are made implicitly available
because they are in the package database.
* It seems to be faster in usual settings.
- In particular, it does not have a preparation phase in which it
merges the dependency information from all home units, so that
its running time does not grow linearly with the size of the
package database in normal Cabal scenarios.
* It is (hopefully) clearer.
* It is better documented.
- - - - -
7 changed files:
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Unit/Env.hs
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/Makefile
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stderr
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stdout
Changes:
=====================================
compiler/GHC/Driver/Downsweep.hs
=====================================
@@ -6,6 +6,8 @@
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ViewPatterns #-}
+{-# OPTIONS_GHC -Wno-invalid-haddock #-}
+
-- | See Note [The ModuleGraph]
module GHC.Driver.Downsweep
( downsweep
@@ -54,8 +56,6 @@ import GHC.Runtime.Context
import Language.Haskell.Syntax.ImpExp
import GHC.Types.UnresolvedImport
-import GHC.Data.Graph.Directed
-import GHC.Data.FastString
import GHC.Data.Maybe ( expectJust )
import qualified GHC.Data.Maybe as M
import GHC.Data.OsPath ( OsPath, unsafeEncodeUtf )
@@ -71,12 +71,15 @@ import GHC.Utils.Logger
import GHC.Utils.Fingerprint
import GHC.Utils.TmpFs
import GHC.Utils.Constants
+import GHC.Utils.Monad (concatMapM)
+import GHC.Utils.Monad.State.Strict
import GHC.Types.Error
import GHC.Types.Target
import GHC.Types.SourceFile
import GHC.Types.SourceError
import GHC.Types.SrcLoc
+import GHC.Types.Unique.Set
import GHC.Types.Unique.Map
import GHC.Types.PkgQual
import GHC.Types.Basic
@@ -91,9 +94,12 @@ import GHC.Unit.Module.Graph
import GHC.Unit.Module.Deps
import qualified GHC.Unit.Home.Graph as HUG
import GHC.Unit.Module.Stage
+import GHC.Unit.External.Index (UnitAbiHash)
import Data.Either ( partitionEithers, lefts )
+import Data.Map (Map)
import qualified Data.Map as Map
+import Data.Set (Set)
import qualified Data.Set as Set
import Control.Concurrent.MVar
@@ -101,7 +107,7 @@ import Control.Monad
import Control.Monad.Trans.Except ( ExceptT(..), runExceptT, throwE )
import qualified Control.Monad.Catch as MC
import Data.Maybe
-import Data.List (partition)
+import Data.List (sort, partition)
import Data.Time
import Data.List (unfoldr)
import Data.Bifunctor (first, bimap)
@@ -864,7 +870,7 @@ getRootSummary excl_mods summ_cache imports_cache hsc_env target
mkPlainErrorMsgEnvelope noSrcSpan (DriverFileNotFound offset_file)
| TargetModule modl <- targetId
= do
- let root_imp = (generatedImport FromTarget (L rootLoc modl))
+ let root_imp = (generatedImport FromTarget (L noSrcSpan modl))
{ ui_pkg_qual = ThisPkg (homeUnitId home_unit) }
maybe_summary <- summariseModule hsc_env home_unit summ_cache imports_cache root_imp
maybe_buf excl_mods
@@ -875,7 +881,6 @@ getRootSummary excl_mods summ_cache imports_cache hsc_env target
where
Target {targetId, targetContents = maybe_buf, targetUnitId = uid} = target
home_unit = ue_unitHomeUnit uid (hsc_unit_env hsc_env)
- rootLoc = mkGeneralSrcSpan (fsLit "<command line>")
dflags = homeUnitEnv_dflags (ue_findHomeUnitEnv uid (hsc_unit_env hsc_env))
-- | Execute 'getRootSummary' for the 'Target's using the parallelism pipeline
@@ -933,52 +938,171 @@ rootSummariesParallel n_jobs hsc_env diag_wrapper msg get_summary = do
-- * Check/validate properties and error out
--------------------------------------------------------------------------------
--- | This function checks then important property that if both p and q are home units
--- then any dependency of p, which transitively depends on q is also a home unit.
+-- | Checks whether the given 'UnitEnv' has the closure property.
--
--- See Note [Multiple Home Units], section 'Closure Property'.
-checkHomeUnitsClosed :: UnitEnv -> [DriverMessages]
-checkHomeUnitsClosed ue
- | Set.null bad_unit_ids = []
- | otherwise = [singleMessage $ mkPlainErrorMsgEnvelope rootLoc $ DriverHomePackagesNotClosed (Set.toList bad_unit_ids)]
+-- See the section “Closure Property” in @Note [Multiple Home Units]@ for the
+-- definition of the closure property and
+-- @Note [Home unit closure property check]@ below for a discussion of the
+-- algorithm used for this check, its justification, and a potential
+-- alternative.
+checkHomeUnitsClosed :: UnitEnv -> [DriverMessages]
+checkHomeUnitsClosed unit_env
+ | null offenders = []
+ | otherwise = [
+ singleMessage $
+ mkPlainErrorMsgEnvelope noSrcSpan $
+ DriverHomePackagesNotClosed (sort offenders)
+ ]
where
- home_id_set = HUG.allUnits $ ue_home_unit_graph ue
- bad_unit_ids = upwards_closure Set.\\ home_id_set {- Remove all home units reached, keep only bad nodes -}
- rootLoc = mkGeneralSrcSpan (fsLit "<command line>")
- downwards_closure :: Graph (Node UnitId UnitId)
- downwards_closure = graphFromEdgedVerticesUniq graphNodes
+ -- | The 'UnitId' and 'HomeUnitEnv' of each home unit.
+ home_unit_data :: [(UnitId, HomeUnitEnv)]
+ home_unit_data = HUG.unitEnv_assocs (ue_home_unit_graph unit_env)
+
+ -- | The 'UnitId's of all home units.
+ home_units :: UniqSet UnitId
+ home_units = mkUniqSet (map fst home_unit_data)
+
+ -- | All offending dependencies. A dependency of a unit /u/ on a unit /v/ is
+ -- offending exactly if /u/ is an external unit reachable from a home unit
+ -- and /v/ is a home unit. Each such dependency is represented in this list
+ -- by the pair of the 'UnitId' of /u/ and the 'UnitId' of /v/.
+ offenders :: [(UnitId, UnitId)]
+ offenders
+ = evalState (collect (map (homeUnitEnv_units . snd) home_unit_data))
+ emptyUniqMap
+ where
- inverse_closure = graphReachability $ transposeG downwards_closure
+ -- | Collects offending dependencies.
+ collect :: [UnitState]
+ -- ^ The 'UnitState's of the home units from which to traverse
+ -- the dependency graph.
+ -> State (UniqMap UnitId (Set UnitAbiHash)) [(UnitId, UnitId)]
+ -- ^ A stateful computation that collects offending dependencies
+ -- that have not yet been found. It uses its state, which is an
+ -- efficent representation of a set of 'GlobalUnitKey's, to
+ -- keep track of which units have already been considered as
+ -- sources of offending dependencies.
+ collect = concatMapM $ \ unit_state ->
+ collect_for_home_unit
+ (unitInfoMap unit_state)
+ (map (toUnitId . fst) $ explicitUnits $ unit_state)
+ where
- upwards_closure = Set.fromList $ map node_key $ allReachableMany inverse_closure [DigraphNode uid uid [] | uid <- Set.toList home_id_set]
+ -- | Collects offending dependencies that are reachable from a particular
+ -- home unit.
+ collect_for_home_unit
+ :: UnitInfoMap
+ -- ^ The 'UnitInfoMap' of the home unit.
+ -> [UnitId]
+ -- ^ The 'UnitId's of the units from which to traverse the dependency
+ -- graph.
+ -> State (UniqMap UnitId (Set UnitAbiHash)) [(UnitId, UnitId)]
+ -- ^ A stateful computation that collects offending dependencies that
+ -- have not yet been found. It uses its state, which is an efficent
+ -- representation of a set of 'GlobalUnitKey's, to keep track of
+ -- which units have already been considered as sources of offending
+ -- dependencies.
+ collect_for_home_unit _ []
+ = return []
+ collect_for_home_unit unit_info_map (current_unit : remaining_units) = do
+ let
+
+ -- | The 'UnitInfo' of the current unit.
+ unit_info :: UnitInfo
+ unit_info
+ = fromMaybe (pprPanic unit_not_found_msg (ppr current_unit)) $
+ lookupUniqMap unit_info_map current_unit
+ where
+
+ -- | The message that says that a unit was not found.
+ unit_not_found_msg :: String
+ unit_not_found_msg = "Unit not found during closure property check"
+
+ -- | The ABI hash of the current unit.
+ unit_abi_hash :: UnitAbiHash
+ unit_abi_hash = unitAbiHash unit_info
+
+ has_been_processed <- gets $ maybe False (Set.member unit_abi_hash) .
+ (`lookupUniqMap` current_unit)
+ if has_been_processed
+ then collect_for_home_unit unit_info_map remaining_units
+ else do
+ modify $ \ processed -> addToUniqMap_C Set.union
+ processed
+ current_unit
+ (Set.singleton unit_abi_hash)
+ let
+
+ -- | The 'UnitId's of the units that the current unit depends on.
+ needed_units :: [UnitId]
+ needed_units = unitDepends unit_info
+
+ -- | The offending dependencies of the current unit.
+ current_offenders :: [(UnitId, UnitId)]
+ current_offenders
+ | current_unit `elementOfUniqSet` home_units
+ = []
+ | otherwise
+ = map ((,) current_unit) $
+ nonDetEltsUniqSet $
+ mkUniqSet needed_units `intersectUniqSets` home_units
+
+ remaining_offenders <- collect_for_home_unit unit_info_map $
+ needed_units ++ remaining_units
+ return $ current_offenders ++ remaining_offenders
- all_unit_direct_deps :: UniqMap UnitId (Set.Set UnitId)
- all_unit_direct_deps
- = HUG.unitEnv_foldWithKey go emptyUniqMap $ ue_home_unit_graph ue
- where
- go rest this this_uis =
- plusUniqMap_C Set.union
- (addToUniqMap_C Set.union external_depends this (Set.fromList $ this_deps))
- rest
- where
- external_depends = mapUniqMap (Set.fromList . unitDepends) (unitInfoMap this_units)
- this_units = homeUnitEnv_units this_uis
- this_deps = [ toUnitId unit | (unit,Just _) <- explicitUnits this_units]
-
- graphNodes :: [Node UnitId UnitId]
- graphNodes = go Set.empty home_id_set
- where
- go done todo
- = case Set.minView todo of
- Nothing -> []
- Just (uid, todo')
- | Set.member uid done -> go done todo'
- | otherwise -> case lookupUniqMap all_unit_direct_deps uid of
- Nothing -> pprPanic "uid not found" (ppr (uid, all_unit_direct_deps))
- Just depends ->
- let todo'' = (depends Set.\\ done) `Set.union` todo'
- in DigraphNode uid uid (Set.toList depends) : go (Set.insert uid done) todo''
+{-
+
+Note [Home unit closure property check]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Per the definition in Note [Multiple Home Units], a unit environment has the
+closure property exactly if there are no paths /h/₁ →* /e/ →* /h/₂ in the
+dependency graph, where /h/₁ and /h/₂ are home units and /e/ is an external
+unit. However, the algorithm used by 'checkHomeUnitsClosed' searches for
+so-called offending dependencies, which are dependencies /e/ → /h/₂ that are
+part of a path /h/₁ →* /e/ → /h/₂ in the dependency graph. To see that this is a
+viable approach, consider the following:
+
+ * A path /h/₁ →* /e/ → /h/₂ is also a path /h/₁ →* /e/ →* /h/₂.
+
+ * For each path /h/₁ →* /e/ →* /h/₂, there exists a path /h/₁ →* /e/′ → /h/₂′,
+ where /e/′ is an external unit and /h/₂′ is a home unit. Such a path can be
+ constructed by taking as /h/₂′ the first home unit on the path /e/ →* /h/₂
+ and as /e/′ the, necessarily external, unit preceding it.
+
+Concretely, the algorithm picks one home unit after the other, determines what
+units it directly depends on, and, starting from them, follows unit dependencies
+to search for offending dependencies. It does not follow dependencies that have
+been followed before, possibly when processing another home unit. To achieve
+this, the algorithm tracks, across home units, from which units it has already
+followed dependencies. For this tracking, it identifies each unit by a 'UnitId'
+and an ABI hash. Using only a 'UnitId' would not work, because 'UnitId's are not
+always globally unique. Also using only an ABI hash is not an option, because an
+ABI hash is not necessarily an ABI hash: it can also be the string @"inline"@.
+
+The correctness of this algorithm rests on the, likely correct, assumption that,
+among the units mentioned in the 'UnitState' of a particular home unit, any unit
+can be uniquely identified by its 'UnitId' and thus 'UnitId' clashes can only
+occur across the 'UnitState's of different home units.
+
+An alternative approach to finding offending dependencies would be to follow
+dependencies starting from all units that /any/ home unit directly depends on
+instead of considering the different home units separately. A corresponding
+algorithm could in principle find the dependencies of a particular unit
+independently of any home unit by fetching the 'UnitInfo' of that unit from the
+'GlobalUnitInfoMap'. However, for such a lookup the algorithm would need not
+only the 'UnitId' but also the ABI hash of the unit in question. Therefore,
+whenever following a dependency of a unit /u/ on a unit /v/, it would have to
+determine the ABI hash of /v/, so that it could later look up /v/’s
+dependencies. The ABI hashes of all units that /u/ depends on should be
+available in the 'unitAbiDepends' field of /u/’s 'UnitInfo'. However, at the
+time of writing, 'unitAbiDepends' never contained anything other than the empty
+list during GHC test runs, which indicated that this alternative solution was
+impossible to realize.
+
+-}
--------------------------------------------------------------------------------
-- * Enable Code Gen for Template Haskell
@@ -1763,7 +1887,7 @@ data NodeRes v
--
-- See also Note [Downsweep Control Flow and Caching]
dfsBuild :: (Ord k, Monad m)
- => Maybe (Map.Map k (NodeRes v))
+ => Maybe (Map k (NodeRes v))
-- ^ Base map, existing results. We won't re-expand any of the nodes
-- already present in this map.
-> [n]
@@ -1773,7 +1897,7 @@ dfsBuild :: (Ord k, Monad m)
-> (n -> m (NodeRes (v,[n])))
-- ^ Expand this node into its payload result and into the list of
-- children nodes to visit next.
- -> m (Map.Map k (NodeRes v))
+ -> m (Map k (NodeRes v))
-- ^ The result accumulates the payload of expanding the root nodes
-- and all nodes transitively reachable from those roots.
dfsBuild base_map roots key expand = go roots (fromMaybe Map.empty base_map)
=====================================
compiler/GHC/Driver/Errors/Ppr.hs
=====================================
@@ -235,10 +235,17 @@ instance Diagnostic DriverMessage where
"but no output will be generated.") $$
(text "There is no module named" <+>
quotes (ppr mod_name) <> text "."))
- DriverHomePackagesNotClosed needed_unit_ids
- -> mkSimpleDecorated $ vcat ([text "Home units are not closed."
- , text "It is necessary to also load the following units:" ]
- ++ map (\uid -> text "-" <+> ppr uid) needed_unit_ids)
+ DriverHomePackagesNotClosed offending_dependencies
+ -> mkSimpleDecorated $
+ hang (text "Some units are not loaded but depend on loaded units.")
+ 4
+ (vcat (map pprDependency offending_dependencies))
+ where
+
+ pprDependency :: (UnitId, UnitId) -> SDoc
+ pprDependency (external_unit, home_unit)
+ = ppr external_unit <+> arrow <+> ppr home_unit
+
DriverInterfaceError reason -> diagnosticMessage (ifaceDiagnosticOpts opts) reason
DriverInconsistentDynFlags msg
=====================================
compiler/GHC/Driver/Errors/Types.hs
=====================================
@@ -369,7 +369,7 @@ data DriverMessage where
DriverRedirectedNoMain :: !ModuleName -> DriverMessage
- DriverHomePackagesNotClosed :: ![UnitId] -> DriverMessage
+ DriverHomePackagesNotClosed :: ![(UnitId, UnitId)] -> DriverMessage
DriverInterfaceError :: !IfaceMessage -> DriverMessage
=====================================
compiler/GHC/Unit/Env.hs
=====================================
@@ -443,13 +443,14 @@ The flow:
Closure Property
----------------
-You must perform a clean cut of the dependency graph.
+A unit environment must have the closure property:
-> Any dependency which is not a home unit must not (transitively) depend on a home unit.
+ No used external unit depends on a home unit.
-For example, if you have three packages p, q and r, then if p depends on q which
-depends on r then it is illegal to load both p and r as home units but not q,
-because q is a dependency of the home unit p which depends on another home unit r.
+More concretely, a unit environment has the closure property exactly if no home
+unit directly or indirectly depends on an external unit that directly or
+indirectly depends on a home unit. 'GHC.Driver.Downsweep.checkHomeUnitsClosed'
+checks whether a given unit environment indeed has this property.
Offsetting Paths
----------------
=====================================
testsuite/tests/driver/multipleHomeUnits/mhu-closure/Makefile
=====================================
@@ -10,14 +10,21 @@ CONFIGURE=configure \
--ghc-options='$(TEST_HC_OPTS)' \
--package-db=../tmp.d
TEST_BUILD='$(TEST_HC)' $(TEST_HC_OPTS) -fhide-source-paths -fforce-recomp
+ONLY_BASE=-hide-all-packages -package base
mhu-closure: clean pkg-database
- $(TEST_BUILD) -unit @unitP
- $(TEST_BUILD) -unit @unitP -unit @unitQ
+ ! $(TEST_BUILD) -unit @unitP
+ ! $(TEST_BUILD) -unit @unitP -unit @unitQ
! $(TEST_BUILD) -unit @unitP -unit @unitR
! $(TEST_BUILD) -unit @unitP -unit @unitR1
$(TEST_BUILD) -unit @unitP -unit @unitQ -unit @unitR
- $(TEST_BUILD) -unit @unitP -unit @unitQ -unit @unitR1
+ ! $(TEST_BUILD) -unit @unitP -unit @unitQ -unit @unitR1
+ $(TEST_BUILD) $(ONLY_BASE) -unit @unitP
+ $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitQ
+ ! $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitR
+ ! $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitR1
+ $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitQ -unit @unitR
+ $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitQ -unit @unitR1
.PHONY: pkg-database
pkg-database:
=====================================
testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stderr
=====================================
@@ -1,10 +1,28 @@
<command line>: error: [GHC-03271]
- Home units are not closed.
- It is necessary to also load the following units:
- - q-0.1.0.0
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
<command line>: error: [GHC-03271]
- Home units are not closed.
- It is necessary to also load the following units:
- - q-0.1.0.0
+ Some units are not loaded but depend on loaded units.
+ r-0.1.0.0 -> q-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ r-0.1.0.0 -> q-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
=====================================
testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stdout
=====================================
@@ -1,3 +1,6 @@
+[1 of 3] Compiling P[p-0.1.0.0]
+[2 of 3] Compiling Q[q-0.1.0.0]
+[3 of 3] Compiling R[r-0.1.0.0]
[1 of 1] Compiling P
[1 of 2] Compiling P[p-0.1.0.0]
[2 of 2] Compiling Q[q-0.1.0.0]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/aacc2e142a3057a5878ba3360e6727…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/aacc2e142a3057a5878ba3360e6727…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/T27828] 3 commits: Change the C types of hs_{bitrev,bswap}{16,32} to match the Haskell types
by Simon Peyton Jones (@simonpj) 23 Sep '26
by Simon Peyton Jones (@simonpj) 23 Sep '26
23 Sep '26
Simon Peyton Jones pushed to branch wip/T27828 at Glasgow Haskell Compiler / GHC
Commits:
545fd4fb by ARATA Mizuki at 2026-09-22T15:03:24-04:00
Change the C types of hs_{bitrev,bswap}{16,32} to match the Haskell types
bitReverse{16,32}# and byteSwap{16,32}# have the type
Word# -> Word#, but their C correspondents took and
returned StgWord{16,32}.
The mismatch on bitReverse16# led to the problem reported
in #27299. Although no similar issue is reported for
bitReverse32# and byteSwap{16,32}#, it seemed wise to
change them proactively.
This commit fixes the mismatch by changing the C type.
Fixes #27299
- - - - -
bf17f289 by fendor at 2026-09-22T15:04:05-04:00
Don't lose instances from shadowed imported modules with the same name
When we look for instances below the current module, we need to check
the unit id as well when we check for whether the module is the current
module, otherwise we ignore modules we import that have the same name as
the import module.
Adds regression test.
- - - - -
b1803ff5 by Simon Peyton Jones at 2026-09-23T22:02:23+01:00
Refactor fundeps yet again
This MR fixes #27828; there was a bad scoping error in `trim_qtvs`.
The main changes are
* Refactor `trim_qtvs` completely to eliminate the bug.
* Remove a redundant `apartnessCheck` from `mkTopOpenFamEqFDs`.
* Use a proper data types, `AmIUnifying` and `OuterKindsFlag`, for two
previously-Boolean arguments to `tc_unify_tys`. This is a pure refactor.
* Lots of improvements to the Notes in FunDeps.hs
- - - - -
24 changed files:
- + changelog.d/26610
- + changelog.d/T27828
- compiler/GHC/Core/Coercion/Axiom.hs
- compiler/GHC/Core/FamInstEnv.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Tc/Instance/FunDeps.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- rts/include/stg/Prim.h
- rts/prim/bitrev.c
- rts/prim/bswap.c
- + testsuite/tests/ghci/prog-mhu008/Makefile
- + testsuite/tests/ghci/prog-mhu008/a/M.hs
- + testsuite/tests/ghci/prog-mhu008/all.T
- + testsuite/tests/ghci/prog-mhu008/b/M.hs
- + testsuite/tests/ghci/prog-mhu008/prog-mhu008.script
- + testsuite/tests/ghci/prog-mhu008/prog-mhu008.stdout
- + testsuite/tests/ghci/prog-mhu008/unitA
- + testsuite/tests/ghci/prog-mhu008/unitB
- + testsuite/tests/indexed-types/should_compile/T27828.hs
- testsuite/tests/indexed-types/should_compile/all.T
- + testsuite/tests/primops/should_run/T27299.hs
- + testsuite/tests/primops/should_run/T27299.stdout
- testsuite/tests/primops/should_run/all.T
Changes:
=====================================
changelog.d/26610
=====================================
@@ -0,0 +1,7 @@
+section: compiler
+synopsis: Fix instance resolution for shadowed modules
+description:
+ Instances imported from modules with the same module name as the importing module
+ were dropped accidentally since we didn't account for the unit id of the imported module.
+mrs: !16648
+issues: #26610
=====================================
changelog.d/T27828
=====================================
@@ -0,0 +1,8 @@
+section: compiler
+synopsis: Fix a "No skolem info" compiler crash
+issues: #27828
+mrs: !16714
+
+description: {
+ There was a bug in the implemenation of functional dependencies for type families.
+}
=====================================
compiler/GHC/Core/Coercion/Axiom.hs
=====================================
@@ -197,14 +197,19 @@ Note [Storing compatibility]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
During axiom application, we need to be aware of which branches are compatible
with which others. The full explanation is in Note [Compatibility] in
-GHc.Core.FamInstEnv. (The code is placed there to avoid a dependency from
+GHC.Core.FamInstEnv. (The code is placed there to avoid a dependency from
GHC.Core.Coercion.Axiom on the unification algorithm.) Although we could
theoretically compute compatibility on the fly, this is silly, so we store it
in a CoAxiom.
-Specifically, each branch refers to all other branches with which it is
-incompatible. This list might well be empty, and it will always be for the
-first branch of any axiom.
+Specifically, the `cab_incomps :: [CoAxBranch]` field of a `CoAxBranch`
+lists all /earlier/ branches with which it is /incompatible/. That is,
+earlier branches where
+ 1) the patterns are not apart from the patterns of this branch, and
+ 2) if the patterns unify, the rhss are different
+
+This list might well be empty, and it will always be for the first branch of
+any axiom.
CoAxBranches that do not (yet) belong to a CoAxiom should have a panic thunk
stored in cab_incomps. The incompatibilities are properly a property of the
@@ -230,7 +235,9 @@ This is checked in FamInstEnv.mkCoAxBranch.
-- If you edit this type, you may need to update the GHC formalism
-- See Note [GHC Formalism] in GHC.Core.Lint
data CoAxiom br
- = CoAxiom -- Type equality axiom.
+ = -- `br` is Unbranched for each of the many axioms of an open type family
+ -- Branched for the single multi-branch axiom of a closed type family
+ CoAxiom -- Type equality axiom.
{ co_ax_unique :: Unique -- Unique identifier
, co_ax_name :: Name -- Name for pretty-printing
, co_ax_role :: Role -- Role of the axiom's equality
=====================================
compiler/GHC/Core/FamInstEnv.hs
=====================================
@@ -19,7 +19,7 @@ module GHC.Core.FamInstEnv (
FamInstMatch(..),
lookupFamInstEnv, lookupFamInstEnvConflicts, lookupFamInstEnvByTyCon,
- isDominatedBy, apartnessCheck, compatibleBranches,
+ isDominatedBy, apartnessCheck, noEarlierMatchCheck, compatibleBranches,
-- Injectivity
InjectivityCheckResult(..),
@@ -488,9 +488,11 @@ in GHC.Core.Unify.)
Note [Compatibility]
~~~~~~~~~~~~~~~~~~~~
Two patterns are /compatible/ if either of the following conditions hold:
-1) The patterns are apart.
-2) The patterns unify with a substitution S, and their right hand sides
-equal under that substitution.
+
+ 1) The patterns are apart.
+
+ 2) The patterns unify with a substitution S, and their right hand sides
+ are equal under that substitution.
For open type families, only compatible instances are allowed. For closed
type families, the story is slightly more complicated. Consider the following:
@@ -603,8 +605,7 @@ injectiveBranches injectivity
ax1@(CoAxBranch { cab_lhs = lhs1, cab_rhs = rhs1 })
ax2@(CoAxBranch { cab_lhs = lhs2, cab_rhs = rhs2 })
-- See Note [Verifying injectivity annotation], case 1.
- = case tcUnifyTysForInjectivity True [rhs1] [rhs2] of
- -- True = two-way pre-unification
+ = case tcUnifyTysForInjectivity Unifying [rhs1] [rhs2] of
Nothing -> InjectivityAccepted
-- RHS are different, so equations are injective.
-- This is case 1A from Note [Verifying injectivity annotation]
@@ -1258,6 +1259,17 @@ apartnessCheck target (CoAxBranch { cab_incomps = incomps })
isSurelyApart SurelyApart = True
isSurelyApart _ = False
+-- | Check whether an earlier branch matches these target types
+noEarlierMatchCheck
+ :: [Type]
+ -> CoAxBranch -- ^ The candidate equation we wish to use
+ -> Bool -- ^ True <=> equation can fire
+noEarlierMatchCheck target (CoAxBranch { cab_incomps = incomps })
+ = not (any matches incomps)
+ where
+ matches earlier_branch
+ = isJust (tcMatchTys (coAxBranchLHS earlier_branch) target)
+
{-
************************************************************************
* *
=====================================
compiler/GHC/Core/Unify.hs
=====================================
@@ -9,6 +9,7 @@ module GHC.Core.Unify (
tcMatchTyX_BM, ruleMatchTyKiX,
-- Side-effect free unification
+ AmIUnifying(..),
tcUnifyTy, tcUnifyTys, tcUnifyFunDeps, tcUnifyDebugger,
tcUnifyTysFG, tcUnifyTysForInjectivity,
BindTvFun, BindFamFun, BindFlag(..),
@@ -597,14 +598,14 @@ tcMatchTyX_BM :: HasDebugCallStack
=> BindTvFun -> Subst
-> Type -> Type -> Maybe Subst
tcMatchTyX_BM bind_tv subst ty1 ty2
- = tc_match_tys_x bind_tv False subst [ty1] [ty2]
+ = tc_match_tys_x bind_tv IgnoreOuterKinds subst [ty1] [ty2]
-- | Like 'tcMatchTy', but allows the kinds of the types to differ,
-- and thus matches them as well.
-- See also Note [tcMatchTy vs tcMatchTyKi]
tcMatchTyKi :: HasDebugCallStack => Type -> Type -> Maybe Subst
tcMatchTyKi ty1 ty2
- = tc_match_tys alwaysBindTv True [ty1] [ty2]
+ = tc_match_tys alwaysBindTv CheckOuterKinds [ty1] [ty2]
-- | This is similar to 'tcMatchTy', but extends a substitution
-- See also Note [tcMatchTy vs tcMatchTyKi]
@@ -614,7 +615,7 @@ tcMatchTyX :: HasDebugCallStack
-> Type -- ^ Target
-> Maybe Subst
tcMatchTyX subst ty1 ty2
- = tc_match_tys_x alwaysBindTv False subst [ty1] [ty2]
+ = tc_match_tys_x alwaysBindTv IgnoreOuterKinds subst [ty1] [ty2]
-- | Like 'tcMatchTy' but over a list of types.
-- See also Note [tcMatchTy vs tcMatchTyKi]
@@ -625,7 +626,7 @@ tcMatchTys :: HasDebugCallStack
-- variables could be free in the target
-- See (CU6) in Note [The Core unifier]
tcMatchTys tys1 tys2
- = tc_match_tys alwaysBindTv False tys1 tys2
+ = tc_match_tys alwaysBindTv IgnoreOuterKinds tys1 tys2
-- | Like 'tcMatchTyKi' but over a list of types.
-- See also Note [tcMatchTy vs tcMatchTyKi]
@@ -635,7 +636,7 @@ tcMatchTyKis :: HasDebugCallStack
-> Maybe Subst -- ^ One-shot substitution
-- See (CU6) in Note [The Core unifier]
tcMatchTyKis tys1 tys2
- = tc_match_tys alwaysBindTv True tys1 tys2
+ = tc_match_tys alwaysBindTv CheckOuterKinds tys1 tys2
-- | Like 'tcMatchTys', but extending a substitution
-- See also Note [tcMatchTy vs tcMatchTyKi]
@@ -645,7 +646,7 @@ tcMatchTysX :: HasDebugCallStack
-> [Type] -- ^ Target
-> Maybe Subst -- ^ One-shot substitution
tcMatchTysX subst tys1 tys2
- = tc_match_tys_x alwaysBindTv False subst tys1 tys2
+ = tc_match_tys_x alwaysBindTv IgnoreOuterKinds subst tys1 tys2
-- | Like 'tcMatchTyKis', but extending a substitution
-- See also Note [tcMatchTy vs tcMatchTyKi]
@@ -655,12 +656,12 @@ tcMatchTyKisX :: HasDebugCallStack
-> [Type] -- ^ Target
-> Maybe Subst -- ^ One-shot substitution
tcMatchTyKisX subst tys1 tys2
- = tc_match_tys_x alwaysBindTv True subst tys1 tys2
+ = tc_match_tys_x alwaysBindTv CheckOuterKinds subst tys1 tys2
-- | Same as tc_match_tys_x, but starts with an empty substitution
tc_match_tys :: HasDebugCallStack
=> BindTvFun
- -> Bool -- ^ match kinds?
+ -> OuterKindsFlag -- ^ Match kinds?
-> [Type]
-> [Type]
-> Maybe Subst
@@ -672,7 +673,7 @@ tc_match_tys bind_me match_kis tys1 tys2
-- | Worker for 'tcMatchTysX' and 'tcMatchTyKisX'
tc_match_tys_x :: HasDebugCallStack
=> BindTvFun
- -> Bool -- ^ match kinds?
+ -> OuterKindsFlag -- ^ Match kinds?
-> Subst
-> [Type]
-> [Type]
@@ -680,8 +681,8 @@ tc_match_tys_x :: HasDebugCallStack
tc_match_tys_x bind_tv match_kis (Subst in_scope id_env tv_env cv_env) tys1 tys2
= case tc_unify_tys neverBindFam -- (ATF7) in Note [Apartness and type families]
bind_tv
- False -- Matching, not unifying
- False -- Not an injectivity check
+ Matching -- Matching, not unifying
+ False -- Not an injectivity check
match_kis
RespectMultiplicities
(mkRnEnv2 in_scope) tv_env cv_env tys1 tys2 of
@@ -706,9 +707,9 @@ ruleMatchTyKiX tmpl_tvs rn_env tenv tmpl target
-- But even if it did, (ATF8) in Note [Apartness and type families]
-- says it doesn't matter becuase here we only care about Unifiable.
-- So neverBindFam is efficient, and sufficient.
- False -- Matching, not unifying
+ Matching -- Matching, not unifying
False -- No doing an injectivity check
- True -- Match the kinds
+ CheckOuterKinds -- Match the kinds
IgnoreMultiplicities
-- See Note [Rewrite rules ignore multiplicities in FunTy]
rn_env tenv emptyCvSubstEnv [tmpl] [target] of
@@ -784,7 +785,7 @@ tcUnifyTy t1 t2 = tcUnifyTys alwaysBindTv [t1] [t2]
tcUnifyDebugger :: Type -> Type -> Maybe Subst
tcUnifyDebugger t1 t2
= case tc_unify_tys_fg
- True -- Unify kinds
+ CheckOuterKinds -- Unify kinds
neverBindFam -- Does not affect Unifiable, so pick max efficient
-- See (ATF8) in Note [Apartness and type families]
alwaysBindTv
@@ -798,7 +799,7 @@ tcUnifyFunDeps :: TyCoVarSet
-> Maybe Subst
tcUnifyFunDeps qtvs tys1 tys2
= case tc_unify_tys_fg
- True -- Unify kinds
+ CheckOuterKinds -- Unify kinds
dontCareBindFam -- Class-instance heads never mention type families
(matchBindTv qtvs)
tys1 tys2 of
@@ -821,7 +822,7 @@ tcUnifyTysForInjectivity unif tys1 tys2
= case tc_unify_tys alwaysBindFam alwaysBindTv
unif -- Am I unifying?
True -- Do injectivity checks
- False -- Don't check outermost kinds
+ IgnoreOuterKinds -- Don't check outermost kinds
RespectMultiplicities
rn_env emptyTvSubstEnv emptyCvSubstEnv
tys1 tys2 of
@@ -838,8 +839,9 @@ tcUnifyTysForInjectivity unif tys1 tys2
-- should never actually be done
maybe_fix tv_subst
- | unif = niFixSubst in_scope tv_subst
- | otherwise = mkTvSubst in_scope tv_subst
+ = case unif of
+ Unifying -> niFixSubst in_scope tv_subst
+ Matching -> mkTvSubst in_scope tv_subst
-- When matching, don't confuse domain with range; no fixpoint!
-----------------
@@ -866,15 +868,15 @@ tcUnifyTysFG :: BindFamFun -> BindTvFun
-> [Type] -> [Type]
-> UnifyResult
tcUnifyTysFG bind_fam bind_tv tys1 tys2
- = tc_unify_tys_fg False bind_fam bind_tv tys1 tys2
+ = tc_unify_tys_fg IgnoreOuterKinds bind_fam bind_tv tys1 tys2
-tc_unify_tys_fg :: Bool
+tc_unify_tys_fg :: OuterKindsFlag
-> BindFamFun -> BindTvFun
-> [Type] -> [Type]
-> UnifyResult
tc_unify_tys_fg match_kis bind_fam bind_tv tys1 tys2
= do { (tv_env, _) <- tc_unify_tys bind_fam bind_tv
- True -- Unifying
+ Unifying
False -- Not doing an injectivity check
match_kis -- Match outer kinds
RespectMultiplicities rn_env
@@ -888,10 +890,10 @@ tc_unify_tys_fg match_kis bind_fam bind_tv tys1 tys2
-- | This function is actually the one to call the unifier -- a little
-- too general for outside clients, though.
tc_unify_tys :: BindFamFun -> BindTvFun
- -> AmIUnifying -- ^ True <=> unify; False <=> match
- -> Bool -- ^ True <=> doing an injectivity check
- -> Bool -- ^ True <=> treat the kinds as well
- -> MultiplicityFlag -- ^ see Note [Rewrite rules ignore multiplicities in FunTy] in GHC.Core.Unify
+ -> AmIUnifying -- ^ Unifying or matching
+ -> Bool -- ^ True <=> doing an injectivity check
+ -> OuterKindsFlag -- ^ Check outer kinds or not
+ -> MultiplicityFlag -- ^ see Note [Rewrite rules ignore multiplicities in FunTy] in GHC.Core.Unify
-> RnEnv2
-> TvSubstEnv -- ^ substitution to extend
-> CvSubstEnv
@@ -910,8 +912,9 @@ tc_unify_tys :: BindFamFun -> BindTvFun
-- See also Note [tcMatchTy vs tcMatchTyKi].
tc_unify_tys bind_fam bind_tv unif inj_check match_kis match_mults rn_env tv_env cv_env tys1 tys2
= initUM tv_env cv_env $
- do { when match_kis $
- unify_tys env kis1 kis2
+ do { case match_kis of
+ CheckOuterKinds -> unify_tys env kis1 kis2
+ IgnoreOuterKinds -> return ()
; unify_tys env tys1 tys2 }
where
env = UMEnv { um_bind_tv_fun = bind_tv
@@ -926,6 +929,11 @@ tc_unify_tys bind_fam bind_tv unif inj_check match_kis match_mults rn_env tv_env
kis2 = map typeKind tys2
+data OuterKindsFlag
+ = CheckOuterKinds -- Unify or match the /kind/ of the two types
+ | IgnoreOuterKinds -- Just unify of match the types, ignoring kinds
+ -- (typically, we already know they are equal)
+
{- *********************************************************************
* *
UnifyResult, MaybeApart etc
@@ -1583,8 +1591,7 @@ c.f. Note [Comparing type synonyms] in GHC.Core.TyCo.Compare
-------------- unify_ty: the main workhorse -----------
-type AmIUnifying = Bool -- True <=> Unifying
- -- False <=> Matching
+data AmIUnifying = Matching | Unifying
type InType = Type -- Before applying the RnEnv2
type OutCoercion = Coercion -- After applying the RnEnv2
@@ -1618,7 +1625,7 @@ unify_ty env (CastTy ty1 co1) ty2 kco
-- See (KCU1) in Note [Kind coercions in Unify]
= maybeApart MARCast -- See (KCU2)
- | um_unif env
+ | Unifying <- um_unif env
= unify_ty env ty1 ty2 (co1 `mkTransCo` kco)
| otherwise -- We are matching, not unifying
@@ -1661,7 +1668,7 @@ unify_ty env (CoercionTy co1) (CoercionTy co2) kco
= do { c_subst <- getCvSubstEnv
; case co1 of
CoVarCo cv
- | not (um_unif env)
+ | Matching <- um_unif env
, not (cv `elemVarEnv` c_subst) -- Not forall-bound
, let (_mult_co, co_l, co_r) = decomposeFunCo kco
-- Because the coercion is used in a type, it should be safe to
@@ -1682,7 +1689,7 @@ unify_ty env (TyVarTy tv1) ty2 kco
= uVarOrFam env (TyVarLHS tv1) ty2 kco
unify_ty env ty1 (TyVarTy tv2) kco
- | um_unif env -- If unifying, can swap args; but not when matching
+ | Unifying <- um_unif env -- If unifying, can swap args; but not when matching
= uVarOrFam (umSwapRn env) (TyVarLHS tv2) ty1 (mkSymCo kco)
-- Deal with TyConApps
@@ -1692,7 +1699,7 @@ unify_ty env ty1 ty2 kco
| Just (tc,tys) <- mb_sat_fam_app1
= uVarOrFam env (TyFamLHS tc tys) ty2 kco
- | um_unif env
+ | Unifying <- um_unif env
, Just (tc,tys) <- mb_sat_fam_app2
= uVarOrFam (umSwapRn env) (TyFamLHS tc tys) ty1 (mkSymCo kco)
@@ -1820,7 +1827,7 @@ uVarOrFam env ty1 ty2 kco
go swapped substs lhs@(TyVarLHS tv1) ty2 kco
| Just ty1' <- lookupVarEnv (um_tv_env substs) tv1'
= -- We already have a substitution for tv1
- if | um_unif env -> unify_ty env ty1' ty2 kco
+ if | Unifying <- um_unif env -> unify_ty env ty1' ty2 kco
| (ty1' `mkCastTy` kco) `tcEqType` ty2 -> return ()
| otherwise -> surelyApart
-- Unifying: recurse into unify_ty
@@ -1842,9 +1849,9 @@ uVarOrFam env ty1 ty2 kco
| TyVarTy tv2 <- ty2
, let tv2' = umRnOccR env tv2
, tv1' == tv2'
- = if | um_unif env -> return ()
- | tv1_is_bindable -> extendTvEnv tv1' ty2
- | otherwise -> return ()
+ = if | Unifying <- um_unif env -> return ()
+ | tv1_is_bindable -> extendTvEnv tv1' ty2
+ | otherwise -> return ()
| tv1_is_bindable
, not (mentionsForAllBoundTyVarsR env ty2_fvs)
@@ -1858,9 +1865,9 @@ uVarOrFam env ty1 ty2 kco
-- e.g. a ~ F p q with `a` not bindable: we might succeed with go_fam
-- e.g. a ~ beta with `a` not bindable: we might be able to bind `beta`
-- e.g. beta ~ F beta Int occurs check; but MaybeApart after swapping
- | um_unif env
+ | Unifying <- um_unif env
, NotSwapped <- swapped -- If we have swapped already, don't do so again
- , Just lhs2 <- canEqLHS_maybe ty2
+ , Just lhs2 <- canEqLHS_maybe ty2
= go IsSwapped substs lhs2 (mkTyVarTy tv1) (mkSymCo kco)
| occurs_check = maybeApart MARInfinite -- Occurs check
@@ -1879,7 +1886,9 @@ uVarOrFam env ty1 ty2 kco
| otherwise
= False
- occurs_check = um_unif env && uOccursCheck substs foralld_tvs lhs rhs
+ occurs_check = case um_unif env of
+ Unifying -> uOccursCheck substs foralld_tvs lhs rhs
+ Matching -> False
-- Occurs check, only when unifying
-- see Note [Infinitary substitutions]
-- Make sure you include `kco` in rhs #14846
@@ -1893,7 +1902,7 @@ uVarOrFam env ty1 ty2 kco
-- Hence the RnEnv2 is empty
| not under_forall
, Just ty1' <- lookupFamEnv (um_fam_env substs) tc1 tys1
- = if | um_unif env -> unify_ty env ty1' ty2 kco
+ = if | Unifying <- um_unif env -> unify_ty env ty1' ty2 kco
-- Below here we are matching
-- The return () case deals with:
-- Template: (F a)..(F a)
@@ -1930,9 +1939,9 @@ uVarOrFam env ty1 ty2 kco
-- NB: a type family can appear on the template when matching
-- see (ATF6) in Note [Apartness and type families]
-- (Only worth doing this if we are not under a forall.)
- | um_unif env
+ | Unifying <- um_unif env
, NotSwapped <- swapped
- , Just lhs2 <- canEqLHS_maybe ty2
+ , Just lhs2 <- canEqLHS_maybe ty2
= go IsSwapped substs lhs2 (mkTyConApp tc1 tys1) (mkSymCo kco)
| otherwise -- See (ATF5) in Note [Apartness and type families]
@@ -1962,9 +1971,9 @@ uVarOrFam env ty1 ty2 kco
(inj_tys2, noninj_tys2) = partitionByList inj tys2
bind_fam_if_poss
- | not (um_unif env) -- Not when matching (ATF11-1)
+ | Matching <- um_unif env -- Not when matching (ATF11-1)
= return ()
- | under_forall -- Not under a forall (ATF3)
+ | under_forall -- Not under a forall (ATF3)
= return ()
| BindMe <- um_bind_fam_fun env tc tys1 rhs1
= unless (uOccursCheck substs emptyVarSet (TyFamLHS tc tys1) rhs1) $
=====================================
compiler/GHC/Driver/Env.hs
=====================================
@@ -263,13 +263,13 @@ hugCompleteSigsBelow hsc uid mn = foldr (++) [] <$>
-- | Find instances visible from the given set of imports
hugInstancesBelow :: HscEnv -> UnitId -> ModuleNameWithIsBoot -> IO (InstEnv, [FamInst])
hugInstancesBelow hsc_env uid mnwib = do
- let mn = gwib_mod mnwib
+ let mn = mkModule uid (gwib_mod mnwib)
(insts, famInsts) <-
unzip . concat <$>
hugSomeThingsBelowUs (\mod_info ->
let details = hm_details mod_info
-- Don't include instances for the current module
- in if moduleName (mi_module (hm_iface mod_info)) == mn
+ in if fmap toUnitId (mi_module (hm_iface mod_info)) == mn
then []
else [(md_insts details, md_fam_insts details)])
True -- Include -hi-boot
=====================================
compiler/GHC/Tc/Instance/FunDeps.hs
=====================================
@@ -136,10 +136,10 @@ data FunDepEqns -- Plural becuase fd_eqs has multiple equations
-- to fresh unification vars,
-- See (IMP2) in Note [Improving against instances]
- , fd_eqs :: [TypeEqn] -- Make these pairs of types equal
- -- Invariant: In each (Pair ty1 ty2), the fd_qtvs may be
- -- free in ty1 but not in ty2. See Wrinkle (1) of
- -- Note [Improving against instances]
+ , fd_eqs :: [TypeEqn] -- Make these pairs of types equal
+ -- Invariant: In each (Pair ty1 ty2), the fd_qtvs may be
+ -- free in ty1 but not in ty2. See Wrinkle (1) of
+ -- Note [Improving against instances]
}
instance Outputable FunDepEqns where
=====================================
compiler/GHC/Tc/Solver/FunDeps.hs
=====================================
@@ -26,12 +26,14 @@ import GHC.Core.Coercion
import GHC.Core.TyCo.Rep( Type(..) )
import GHC.Core.Predicate( EqRel(..) )
import GHC.Core.TyCon
-import GHC.Core.Unify( tcUnifyTysForInjectivity, typeListsAreApart )
+import GHC.Core.Unify( AmIUnifying(..)
+ , tcUnifyTysForInjectivity, typeListsAreApart )
import GHC.Core.Coercion.Axiom
import GHC.Core.TyCo.Subst( elemSubst )
import GHC.Builtin.WiredIn.TypeLits( tryInteractTopFam, tryInteractInertFam )
+import GHC.Types.Var( TyVar, tyVarKind, setTyVarKind )
import GHC.Types.Var.Set
import GHC.Utils.Outputable
@@ -39,7 +41,7 @@ import GHC.Utils.Panic
import Control.Monad( unless )
import GHC.Data.Pair
-import Data.Maybe( isNothing, isJust, mapMaybe )
+import Data.Maybe( isJust, mapMaybe )
{- Note [Overview of functional dependencies in type inference]
@@ -109,7 +111,6 @@ Wrinkles
from fundeps, but that would require new evidence forms, and an extension to
FC, so we don't do that right now (Dec 14).
-
Note [FunDep and implicit parameter reactions]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Currently, our story of interacting two dictionaries (or a dictionary
@@ -573,6 +574,7 @@ tryEqFunDeps work_item@(EqCt { eq_lhs = work_lhs
tryFamEqFunDeps :: TcSMode -> [EqCt] -> TyCon -> [TcType] -> EqCt -> SolverStage ()
+-- See Note [Type inference for type families with injectivity]
tryFamEqFunDeps mode eqs_for_me fam_tc work_args
work_item@(EqCt { eq_ev = ev, eq_rhs = work_rhs })
| Just ops <- builtInClosedTyFamTyCon_maybe fam_tc
@@ -583,6 +585,7 @@ tryFamEqFunDeps mode eqs_for_me fam_tc work_args
; tryFDEqns False fam_tc work_args work_item eqns
; unless (hasRelevantGiven eqs_for_me work_args work_item) $
+ -- hasRelevantGiven: See (CF1) in Note [Exploiting closed type families]
do { eqns <- mkTopBuiltinFamEqFDs fam_tc ops work_args work_rhs
; tryFDEqns True fam_tc work_args work_item eqns } }
@@ -599,8 +602,11 @@ tryFamEqFunDeps mode eqs_for_me fam_tc work_args
NotInjective -> nopStage ()
Injective inj -> do { eqns <- mkLocalFamEqFDs eqs_for_me fam_tc inj work_args work_rhs
; tryFDEqns False fam_tc work_args work_item eqns }
+ -- NB: tryFDEqns bales out on an insoluble fundep
+ -- See (CF4) in Note [Exploiting closed type families]
; unless (hasRelevantGiven eqs_for_me work_args work_item) $
+ -- hasRelevantGiven: See (CF1) in Note [Exploiting closed type families]
do { eqns <- mkTopFamEqFDs fam_tc work_args work_item
; tryFDEqns True fam_tc work_args work_item eqns } }
@@ -638,10 +644,11 @@ tryFDEqns is_top fam_tc work_args work_item@(EqCt { eq_ev = ev, eq_rhs= rhs }) f
-- User-defined type families
-----------------------------------------
mkTopClosedFamEqFDs :: CoAxiom Branched -> [TcType] -> EqCt -> SolverStage [FunDepEqns]
+-- Implements (INJFAM:Wanted/top-closed)
+-- See Note [Exploiting closed type families]
-- Look at the top-level axioms; we effectively infer injectivity,
--- so we don't need tyConInjectivtyInfo. This works fine for closed
+-- so we don't need tyConInjectivityInfo. This works fine for closed
-- type families without injectivity info
--- See Note [Exploiting closed type families]
mkTopClosedFamEqFDs ax work_args (EqCt { eq_ev = ev, eq_rhs = work_rhs })
| isGenerativeType work_rhs -- See (CF5) in Note [Exploiting closed type families]
= Stage $
@@ -679,39 +686,46 @@ hasRelevantGiven eqs_for_me work_args (EqCt { eq_rhs = work_rhs })
relevant (EqCt { eq_ev = ev, eq_lhs = lhs, eq_rhs = rhs_ty })
| isGiven ev
, TyFamLHS _ lhs_tys <- lhs
- = isJust (tcUnifyTysForInjectivity True work_tys (rhs_ty:lhs_tys))
+ = isJust (tcUnifyTysForInjectivity Unifying work_tys (rhs_ty:lhs_tys))
| otherwise
= False
getRelevantBranches :: CoAxiom Branched -> [TcType] -> Xi -> [FunDepEqns]
-- Return the FunDepEqns that arise from each relevant branch
+-- Implements Note [Relevance]
getRelevantBranches ax work_args work_rhs
- = go [] (fromBranches (coAxiomBranches ax))
+ = go (fromBranches (coAxiomBranches ax))
where
work_tys = work_rhs : work_args
- go _ [] = []
- go preceding (branch:branches)
+ go [] = []
+ go (branch:branches)
= case is_relevant branch of
- Just eqn -> eqn : go (branch:preceding) branches
- Nothing -> go (branch:preceding) branches
+ Just eqn -> eqn : go branches
+ Nothing -> go branches
where
- is_relevant (CoAxBranch { cab_tvs = qtvs, cab_lhs = lhs_tys, cab_rhs = rhs_ty })
- | Just subst <- tcUnifyTysForInjectivity True (rhs_ty:lhs_tys) work_tys
- , let (subst', qtvs') = trim_qtvs subst qtvs
- lhs_tys' = substTys subst' lhs_tys
- rhs_ty' = substTy subst' rhs_ty
- , all (no_match lhs_tys') preceding
+ is_relevant branch@(CoAxBranch { cab_tvs = qtvs
+ , cab_lhs = lhs_tys
+ , cab_rhs = rhs_ty })
+ | Just subst <- tcUnifyTysForInjectivity Unifying (rhs_ty:lhs_tys) work_tys
+ -- See (RW1)-(RW3) in Note [Relevance]
+ -- This is a pre-/unification/ check (not matching)
+ -- so `subst` can bind both `qtvs` and fvs(work_tys)
+ , let (subst',qtvs') = trim_qtvs subst qtvs
+ lhs_tys' = substTys subst' lhs_tys
+ rhs_ty' = substTy subst' rhs_ty
+ branch_tys' = rhs_ty' : lhs_tys'
+ , noEarlierMatchCheck lhs_tys' branch -- See (RW4) in Note [Relevance]
= Just (FDEqns { fd_qtvs = qtvs'
- , fd_eqs = zipWith Pair (rhs_ty':lhs_tys') work_tys })
+ , fd_eqs = zipWith Pair branch_tys' work_tys })
+ -- Do not apply the substition to `work_tys`;
+ -- See (CF7) in Note [Exploiting closed type families]
| otherwise
= Nothing
- no_match lhs_tys (CoAxBranch { cab_lhs = lhs_tys1 })
- = isNothing (tcUnifyTysForInjectivity False lhs_tys1 lhs_tys)
-
mkTopOpenFamEqFDs :: TyCon -> [Bool] -> [TcType] -> EqCt -> TcS [FunDepEqns]
--- Implements (INJFAM:Wanted/top)
+-- Implements (INJFAM:Wanted/top-open)
+-- See Note [Exploiting open type families]
mkTopOpenFamEqFDs fam_tc inj_flags work_args (EqCt { eq_rhs = work_rhs })
= do { fam_envs <- getFamInstEnvs
; let branches :: [CoAxBranch]
@@ -720,15 +734,15 @@ mkTopOpenFamEqFDs fam_tc inj_flags work_args (EqCt { eq_rhs = work_rhs })
; return (mapMaybe do_one branches) }
where
do_one :: CoAxBranch -> Maybe FunDepEqns
- do_one branch@(CoAxBranch { cab_tvs = branch_tvs
- , cab_lhs = branch_lhs_tys
- , cab_rhs = branch_rhs })
- | Just subst <- tcUnifyTysForInjectivity False [branch_rhs] [work_rhs]
- -- False: matching, not unifying
- , let (subst', qtvs) = trim_qtvs subst branch_tvs
+ do_one (CoAxBranch { cab_tvs = branch_qtvs
+ , cab_lhs = branch_lhs_tys
+ , cab_rhs = branch_rhs })
+ | Just subst <- tcUnifyTysForInjectivity Matching [branch_rhs] [work_rhs]
+ , let (subst', qtvs') = trim_qtvs subst branch_qtvs
branch_lhs_tys' = substTys subst' branch_lhs_tys
- , apartnessCheck branch_lhs_tys' branch -- See (TIF3)
- = Just (mkInjectivityFDEqn inj_flags qtvs branch_lhs_tys' work_args)
+ -- No need for an apartness check here; for open type families
+ -- there are no "preceding" equations
+ = Just (mkInjectivityFDEqn inj_flags qtvs' branch_lhs_tys' work_args)
| otherwise
= Nothing
@@ -736,7 +750,7 @@ mkTopOpenFamEqFDs fam_tc inj_flags work_args (EqCt { eq_rhs = work_rhs })
mkLocalFamEqFDs :: [EqCt] -> TyCon -> [Bool] -> [TcType] -> Xi -> SolverStage [FunDepEqns]
-- Wanted constraints only
-- Both open and closed type families, but only ones with declared injectivity
--- See Note [Type inference for type families with injectivity] esp (TIF2)
+-- See Note [Exploiting local type-family injectivity]
mkLocalFamEqFDs eqs_for_me fam_tc inj_flags work_args work_rhs
= do { let -- eqns_from_inerts: see (INJFAM:Wanted/other)
eqns_from_inerts = mapMaybe do_one eqs_for_me
@@ -755,15 +769,23 @@ mkLocalFamEqFDs eqs_for_me fam_tc inj_flags work_args work_rhs
mk_eqn iargs = mkInjectivityFDEqn inj_flags [] work_args iargs
-trim_qtvs :: Subst -> [TcTyVar] -> (Subst,[TcTyVar])
--- Tricky stuff: see (TIF1) in
--- Note [Type inference for type families with injectivity]
-trim_qtvs subst [] = (subst, [])
-trim_qtvs subst (tv:tvs)
- | tv `elemSubst` subst = trim_qtvs subst tvs
- | otherwise = let !(subst1, tv') = substTyVarBndr subst tv
- !(subst', tvs') = trim_qtvs subst1 tvs
- in (subst', tv':tvs')
+trim_qtvs :: Subst -> [TyVar] -> (Subst, [TyVar])
+-- Tricky stuff: see (OF1) in Note [Exploiting open type families]
+-- The returned substitution is identical to the incoming one, except that
+-- its in-scope set is extended with the returned [TyVar]
+trim_qtvs unif_subst qtvs
+ = go unif_subst qtvs
+ where
+ go :: Subst -> [TyVar] -> (Subst, [TyVar])
+ go subst [] = (subst, [])
+ go subst (tv:tvs)
+ | tv `elemSubst` unif_subst = go subst tvs
+ | otherwise = (subst'', tv':tvs')
+ where
+ tv' = tv `setTyVarKind` substTy subst (tyVarKind tv)
+ subst' = subst `extendSubstInScope` tv'
+ !(subst'', tvs') = go subst' tvs
+
-----------------------------------------
-- Built-in type families
@@ -924,15 +946,20 @@ we attempt to exploit injectivity, via `mkLocalFamEqFDs`:
* (INJFAM:Wanted/other) see `mkLocalFamEqFDs`
work item: [W] F s1 s2 ~ rhs -- Wanted
inert: [G/W] F t2 t2 ~ rhs -- Same `rhs`, Given or Wanted
- We can generate FunDepEqns: (s2 ~ t2)
+ See Note [Exploiting local type-family injectivity]
+
+* (INJFAM:Wanted/top-open) for open type families: `mkTopOpenFamEqFDs`
+ type family F a b = r | r -> b
+ type instance F Int (Maybe a) = [G Int] -- G is a type family
+ [W] F alpha beta = [ty]
+ We can generate (Maybe gamma ~ beta)
+ See Note [Exploiting open type families]
-* (INJFAM:Wanted/top) see `mkTopUserFamEqFDs`
- work item: [W] F s1 s2 ~ rhs
- type instance forall a b c. F t1 t2 ~ top_rhs
- and we can /match/ the LHS, so that
- S(top_rhs) = rhs
- then we can generate the FunDepEqns: forall a c. s2 ~ S(t2)
- But see wrinkle (TIF1), (TIF3)
+* (INJFAM:Wanted/top-closed) for closed type families: `mkTopClosedFamEqFDs`
+ type family F a b where { ...eqns... }
+ [W] F alpha ~ Int
+ We may be able to generate some extra equalities to constraint `alpha`
+ See very clever Note [Exploiting closed type families]
For /built-in/ type families, it's pretty similar, except that
@@ -945,45 +972,36 @@ For /built-in/ type families, it's pretty similar, except that
* mkLocalBuiltinFamEqFDs
* mkTopBuiltinFamEqFDs
-(TIF1) Generating fundeps from a top-level type instance is covered in
- Section 5.2 in the Injective Type Families paper. It's a bit tricky.
- Consider
- type family F @k (a::k) (b::k) = r | r -> k b
- type instance forall k (a::k) (b::k). F @k (Proxy @k a) (Proxy @k b) = Proxy @k a
- [W] F @kappa alpha beta ~ Maybe (Proxy @kappa (delta::kappa))
+Note [Exploiting local type-family injectivity] see `mkLocalFamEqFDs`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Suppose we have a type family with declared injectivity:
+ type family F a b = r | r -> b
+and we have
+ work item: [W] F s1 s2 ~ F t1 t2
+or
+ work item: [W] F s1 s2 ~ rhs -- Wanted
+ inert: [G/W] F t2 t2 ~ rhs -- Same `rhs`, Given or Wanted
- we match (Proxy @kappa delta) against the template (Proxy k a), succeeding
- with substitution [k:->kappa, a:->delta]. We want to generate this FunDepEqns
- FDEqn { fd_qtvs = [b:kappa], fd_eqs = [ beta ~ Proxy @kappa b ] }
- Notice that
- * we must quantify the FunDepEqns over `b`, which is not matched; for this
- we will generate a fresh unification variable in `instantiateFunDepEqn`.
- * we must substitute `k:->kappa` in the kind of `b`.
- This fancy footwork for `fd_qtvs` is done by `trim_qtvs` in
- `mkInjWantedFamEqTopEqns`.
+Then we can generate FunDepEqns: (s2 ~ t2)
+
+This applies equally to /closed/ type families; it is /not/ subsumed
+by Note [Exploiting closed type families]. Consider:
-(TIF2) All this applies equally to /closed/ type families; it is /not/
- subsumed by Note [Exploiting closed type families]. Consider:
type family F a | r -> a where { .... }
[W] F t1 ~ a
[W] F t2 ~ a
- Then since F is declared injective, we can generate t1~t2.
+Then since F is declared injective, we can generate t1~t2.
- As for open type families, we insist on /user-declared/ injectivity only; we
- don't try to /infer/ injectivity even for a closed family. See Section 3.4
- of the "Injective type families" paper. (Arguably, we could /infer/
- injectivity for closed type families, and that would be more in the spirit of
- Note [Exploiting closed type families].)
+As for open type families, we insist on /user-declared/ injectivity only; we
+don't try to /infer/ injectivity even for a closed family. See Section 3.4
+of the "Injective type families" paper. (Arguably, we could /infer/
+injectivity for closed type families, and that would be more in the spirit of
+Note [Exploiting closed type families].)
-(TIF3) Further to (TIF1), if we are considering a /closed/ type family, we
- must ensure (see Section 5.2 of the paper) that after matching that
- equation would indeed be the one to fire. So we call `apartnessCheck`
- on the branch to ensure this, in `mkTopUserFamEqFDs`.
-
-Definition [Relevance]
-~~~~~~~~~~~~~~~~~~~~~~
+Note [Relevance]
+~~~~~~~~~~~~~~~~
We say that a closed-type-family equation `F lhs = rhs` is
/relevant/ for a Wanted [W] F wlhs ~ wrhs
iff
@@ -992,6 +1010,10 @@ iff
(R2) There is no earlier equation that matches S(lhs). See (RW4) below.
+The relevance check is implemented by `getRelevantBranches`, which acutally
+returns the [FunDepEqns] described in the Closed Family Fundep Algorithm in
+Note [Exploiting closed type families].
+
(RW1) Pre-unification treats type-family applications as binding to anything,
rather like type variables. If two types don't even pre-unify, we say that they
are /apart/. It is done by `tcUnifyTysForInjectivity`.
@@ -1014,24 +1036,82 @@ iff
Clearly the RHS is apart from the first equation and we want to fire injectivity
on the second equation.
-(RW4) Why "no earlier equation matches" in conditoin (R2)? Consider the family
+(RW4) Why "no earlier equation matches" in condition (R2)? Consider the family
type family Bak a = r where
Bak Int = Char -- B1
Bak Char = Int -- B2
Bak a = a -- B3
- and [W] Bak alpha ~ Char. In fact, only (B2) is relevant for this Wanted.
+ and [W] Bak alpha ~ Char. In fact, only (B1) is relevant for this Wanted.
You might think that (B3) could be instantiated to Bak Char ~ Char; but
actually that instantiation will never fire because (B2) Bak Char ~ Int would
- fire first. So the only way to return a Char is if the argment is Int; so we
+ fire first. So the only way to return a Char is via (B1); so we
can emit [W] alpha ~ Int. Hence (B3) is not relevant; only (B2) is relevant.
That is the reason for condition (R2) in the definition of Relevance above.
A watertight proof that this is the Right Thing is not very easy. See more
- discussion in #23162.
+ discussion in #23162, and Section 5.2 of the paper.
-Note [Exploiting closed type families]
+ How, precisely, do we implement (R2)? We check that there is no earlier equation
+ that fires on S(lhs), in this case (on Bak Char). Notice that this is different
+ from the `apartnessCheck`, which checks that all preceding equations are apart
+ from S(lhs). Apartness checking uses /unification/; here we want /matching/.
+ Hence using `noEarlierMatchCheck`, not `apartnessCheck`.
+
+ Here's a good example from T27171_aux. T
+ type family TMessage m where
+ {- T1 -} TMessage @f @t (CustomMethod s :: Method f t) = ()
+ {- T2 -} TMessage @f @Req (m :: Method f Req) = TRequestMessage m
+ {- T3 -} TMessage @f @Not (m :: Method f Not) = TNotificationMessage m
+
+ [W] TMessage @SC @Req alpha ~# TRequestMessage alpha
+
+ There is only one relevant equation, namely (T2). If we apply its
+ pre-unification substitution [f :-> SC, m :-> alpha] to its LHS we get
+ TMessage @SC @Req alpha
+ and equation (T1) does not match that. (It does unify, but we don't care.)
+
+Note [Exploiting open type families] see `mkTopOpenFamEqFDs`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Generating fundeps from a top-level type instance is covered in Section 5.2 in
+the Injective Type Families paper. For open type families, suppose we have
+
+ type family F a b = r | r -> b
+ type instance F Int (Maybe a) = [G Int] -- G is a type family
+
+ [W] F alpha beta = [ty]
+
+Then, since F has been checked as injective, and the RHS [G Int]
+pre-unifies with [ty], we can add a derived FunDepEqns
+ FDEqns{ fd_qtvs = a, fd_eqs = [ Maybe a ~ beta ] }
+and thereby emit
+ [W] Maybe gamma ~ beta -- Fresh gamma
+
+Wrinkles
+
+(OF1) Consider
+ type family F @k (a::k) (b::k) = r | r -> k b
+ type instance forall k (a::k) (b::k).
+ F @k (Proxy @k a) (Proxy @k b) = Maybe (Proxy @k a)
+
+ [W] F @kappa alpha beta ~ Maybe (Proxy @kappa (delta::kappa))
+
+ We match the target (Maybe (Proxy @kappa delta))
+ against the template (Maybe (Proxy @k a))
+ succeeding with substitution [k:->kappa, a:->delta]. We want to generate this:
+ FDEqn { fd_qtvs = [b::kappa], fd_eqs = [ Proxy @kappa b ] ~ beta }
+ Notice that
+ * we must quantify the FunDepEqns over `b`, which is not matched; for this
+ we will generate a fresh unification variable in `instantiateFunDepEqn`.
+ * we must substitute `k:->kappa` in the kind of `b`.
+
+ This fancy footwork for `fd_qtvs` is done by `trim_qtvs`. It
+ * Drops a quantified tyvar that /is/ matched
+ * Substitutes in the kind of a quantified tyvar that is /not/ matched
+ * Adds the not-matched tyvar to the in-scope set of the substitution
+
+Note [Exploiting closed type families] see `mkTopClosedFamEqFDs`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppose we have
type family F a b where
@@ -1042,17 +1122,18 @@ Suppose we have
[W] F Int alpha ~ Char
The /only/ way to solve this Wanted is using (F2), so we can safely unify
-alpha:=Char without risking losing any solutions. That is what
-`mkTopClosedFamEqFDs` does. Ticket #23162 has lots of background detail
+alpha:=Char without risking losing any solutions. We don't even need any
+injectivity annotations. Ticket #23162 has lots of background detail.
-More precisely, here is the Closed Family Fundep Algorithm (CFFA)
+More precisely, here is the very clever Closed Family Fundep Algorithm (CFFA)
IF * F a is a closed type family.
* We are trying to solve [W] F wlhs ~ wrhs.
- * There are no "relevant" Givens [G] F lhs ~ rhs. See (CF1) below.
- * F has exactly one equation, F lhs = rhs that is "relevant" for that Wanted
+ * There are no "relevant Givens" [G] F lhs ~ rhs. See (CF1) below.
+ * F has exactly one equation, F lhs = rhs that is "relevant" for
+ that Wanted (see Note [Relevance])
THEN
- we can emit and solve the fundep equalities:
+ we can emit and solve the fundeps :: [FunDepEqns]:
[W] wlhs1 ~ lhs1
...
[W] wlhsn ~ lhsn
@@ -1060,7 +1141,10 @@ More precisely, here is the Closed Family Fundep Algorithm (CFFA)
with fresh unification vars in lhs and rhs for the quantified variables of the
equation.
-See Definition [Relevance] for what "relevant" means.
+ Actually we take advantage of the substitution generated by the relevance
+ check, see (CF7) below.
+
+See Note [Relevance] for what "relevant" means.
We need to take care about non-termination; see (CF3).
Key point: equations that are not relevant do not need to be considered for fundeps at all.
@@ -1166,6 +1250,8 @@ Key point: equations that are not relevant do not need to be considered for fund
I was looking at non-termination for closed type families, but it's a small
improvement in general.
+ This bale-out is implementedn in `tryFDEqns`.
+
(CF5) Consider (see "Yikes5" in #23162):
type family F a where
F (Just x) = Int
@@ -1196,7 +1282,7 @@ Key point: equations that are not relevant do not need to be considered for fund
type family I t = res | res -> t where
I TInt = Int |> g -- where g :: Type ~# IK k
and [W] I alpha ~ Int |> g2
- Here we definiteily want to take advantage of injectivity.
+ Here we definitely want to take advantage of injectivity.
(CF6) This machinery can also have a significant positive effect on the size of
proof terms. For example (simplification of T26426):
@@ -1204,7 +1290,8 @@ Key point: equations that are not relevant do not need to be considered for fund
type family (++) a b where { '[] ++ ys = ys; (x:xs) ++ ys = x : (xs ++ ys) }
type family MapId a where { MapId '[] = '[]; MapId (x:xs) = x : MapId xs }
- app :: (MapId xs ++ MapId ys ~ MapId (xs ++ ys)) => Proxy xs -> Proxy ys -> Proxy (xs ++ ys)
+ app :: (MapId xs ++ MapId ys ~ MapId (xs ++ ys))
+ => Proxy xs -> Proxy ys -> Proxy (xs ++ ys)
test :: Proxy [ty_1, ..., ty_n]
test = Proxy @'[ty_1]
@@ -1248,6 +1335,30 @@ Key point: equations that are not relevant do not need to be considered for fund
instead of relying on recursively built sub-proof terms, which brings down
coercion sizes (in certain situations) from O(n^3) to O(n^2).
+(CF7) Relevance. When computing relevance in the Closed Family Fundep Algorithm,
+ for [W] F wlhs1 wlhs2 ~ wrhs, against an equation F lhs1 lhs2 ~ rhs
+ we get back a pre-unifying substitution S that makes the two as equal as poss.
+ Then we use `trim_qtvs` in exactly the same way as in
+ (OF1) of Note [Exploiting closed type families], to generate qtvs' and S'
+ Then we generate
+ FDEqns { fd_qtvs = qtvs', fd_eqs [ S'(lhs1) ~ wlhs1
+ , S'(lhs2) ~ wlhs2
+ , S'(rhs) ~ wrhs ] }
+ Notice that we do /not/ apply S' to wlhs/wrhs. These type contain unification
+ variables that we must actually unify! Example
+ type familiy F a b where
+ F [a] (Maybe b) = (a, G b)
+ [W] F alpha beta ~ (Int, [gamma])
+ Pre-unification gives [alpha :-> [a], beta :-> Maybe b, a :-> Int]
+ This substitution eliminates the quantified variable `a` but not `b`, so we
+ want this:
+ FDEqns { fd_qtvs = [b], fd_eqs [ [Int] ~ alpha
+ , Maybe b ~ beta
+ , (Int,G b) ~ (Int, [gamma]) ] }
+
+ Notice also that by applying the substitution to the template but not to the
+ Wanted, we uphold the `fd_eqs` invariant in `FDEqns` (see its data type decl)
+
Note [Cache-caused loops]
~~~~~~~~~~~~~~~~~~~~~~~~~
It is very dangerous to cache a rewritten wanted family equation as 'solved' in
@@ -1340,28 +1451,29 @@ solveFunDeps work_ev fd_eqns
; uPairsTcM uenv eqs }
instantiateFunDepEqns :: FunDepEqns -> TcM [TypeEqn]
-instantiateFunDepEqns (FDEqns { fd_qtvs = tvs, fd_eqs = eqs })
- | null tvs
+instantiateFunDepEqns (FDEqns { fd_qtvs = qtvs, fd_eqs = eqs })
+ | null qtvs
= return rev_eqs
| otherwise
- = do { TcM.traceTc "instantiateFunDepEqns" (ppr tvs $$ ppr eqs)
- ; (_, subst) <- instFlexiXTcM emptySubst tvs -- Takes account of kind substitution
+ = do { TcM.traceTc "instantiateFunDepEqns" (ppr qtvs $$ ppr eqs)
+ ; (_, subst) <- instFlexiXTcM emptySubst qtvs -- Takes account of kind substitution
; return (map (subst_pair subst) rev_eqs) }
where
rev_eqs = reverse eqs
-- (reverse eqs): See Note [Reverse order of fundep equations]
subst_pair subst (Pair ty1 ty2)
- = Pair (substTyUnchecked subst' ty1) ty2
+ = Pair (substTy subst' ty1) (substTy subst' ty2)
+-- ToDo not correct!
-- ty2 does not mention fd_qtvs, so no need to subst it.
-- See GHC.Tc.Instance.Fundeps Note [Improving against instances]
- -- Wrinkle (1)
+ -- Wrinkle (IMP1)
where
- subst' = extendSubstInScopeSet subst (tyCoVarsOfType ty1)
+ subst' = extendSubstInScopeSet subst (tyCoVarsOfTypes [ty1,ty2])
-- The free vars of ty1 aren't just fd_qtvs: ty1 is the result
-- of matching with the [W] constraint. So we add its free
-- vars to InScopeSet, to satisfy substTy's invariants, even
- -- though ty1 will never (currently) be a poytype, so this
+ -- though ty1 will never (currently) be a polytype, so this
-- InScopeSet will never be looked at.
=====================================
rts/include/stg/Prim.h
=====================================
@@ -59,16 +59,16 @@ StgWord hs_xchg32(StgWord x, StgWord val);
StgWord64 hs_xchg64(StgWord x, StgWord64 val);
/* rts/prim/bswap.c */
-StgWord16 hs_bswap16(StgWord16 x);
-StgWord32 hs_bswap32(StgWord32 x);
+StgWord hs_bswap16(StgWord x);
+StgWord hs_bswap32(StgWord x);
StgWord64 hs_bswap64(StgWord64 x);
/* rts/prim/bitrev.c
This was done as part of issue #16164.
See Note [Bit reversal primop] for more details about the implementation.*/
StgWord hs_bitrev8(StgWord x);
-StgWord16 hs_bitrev16(StgWord16 x);
-StgWord32 hs_bitrev32(StgWord32 x);
+StgWord hs_bitrev16(StgWord x);
+StgWord hs_bitrev32(StgWord x);
StgWord64 hs_bitrev64(StgWord64 x);
/* rts/prim/longlong.c */
=====================================
rts/prim/bitrev.c
=====================================
@@ -36,8 +36,8 @@ hs_bitrev8(StgWord x)
return x;
}
-StgWord16
-hs_bitrev16(StgWord16 x)
+StgWord
+hs_bitrev16(StgWord x)
{
x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1 );
x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2 );
@@ -46,14 +46,14 @@ hs_bitrev16(StgWord16 x)
return x;
}
-StgWord32
-hs_bitrev32(StgWord32 x)
+StgWord
+hs_bitrev32(StgWord x)
{
- x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1 );
- x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2 );
- x = ((x >> 4) & 0x0F0F0F0F) | ((x & 0x0F0F0F0F) << 4 );
- x = ((x >> 8) & 0x00FF00FF) | ((x & 0x00FF00FF) << 8 );
- x = ( x >> 16 ) | ( x << 16 );
+ x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1 );
+ x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2 );
+ x = ((x >> 4) & 0x0F0F0F0F) | ((x & 0x0F0F0F0F) << 4 );
+ x = ((x >> 8) & 0x00FF00FF) | ((x & 0x00FF00FF) << 8 );
+ x = ((x >> 16) & 0x0000FFFF) | ((x & 0x0000FFFF) << 16);
return x;
}
=====================================
rts/prim/bswap.c
=====================================
@@ -1,16 +1,18 @@
#include "Rts.h"
-StgWord16
-hs_bswap16(StgWord16 x)
+StgWord
+hs_bswap16(StgWord x)
{
- return ((x >> 8) | (x << 8));
+ x = (StgWord16)x;
+ return (StgWord16)((x >> 8) | (x << 8));
}
-StgWord32
-hs_bswap32(StgWord32 x)
+StgWord
+hs_bswap32(StgWord x)
{
- return ((x >> 24) | ((x >> 8) & 0xff00) |
- (x << 24) | ((x & 0xff00) << 8));
+ x = (StgWord32)x;
+ return (StgWord32)((x >> 24) | ((x >> 8) & 0xff00) |
+ (x << 24) | ((x & 0xff00) << 8));
}
StgWord64
=====================================
testsuite/tests/ghci/prog-mhu008/Makefile
=====================================
@@ -0,0 +1,3 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
=====================================
testsuite/tests/ghci/prog-mhu008/a/M.hs
=====================================
@@ -0,0 +1,4 @@
+module M (T (..)) where
+
+newtype T = MkT Int
+ deriving (Eq, Ord)
=====================================
testsuite/tests/ghci/prog-mhu008/all.T
=====================================
@@ -0,0 +1,5 @@
+test('prog-mhu008',
+ [extra_files(['a/', 'b/', 'unitA', 'unitB']),
+ cmd_prefix('ghciWayFlags=' + config.ghci_way_flags),
+ req_interp],
+ ghci_multiunit_script, [['unitA', 'unitB'], 'prog-mhu008.script'])
=====================================
testsuite/tests/ghci/prog-mhu008/b/M.hs
=====================================
@@ -0,0 +1,11 @@
+{-# LANGUAGE PackageImports #-}
+
+module M
+ ( module Export
+ , cmp
+ ) where
+
+import "a" M as Export
+
+cmp :: T -> T -> Bool
+cmp x y = x <= y
=====================================
testsuite/tests/ghci/prog-mhu008/prog-mhu008.script
=====================================
@@ -0,0 +1,5 @@
+:set -XPackageImports
+import "a" M qualified as MA
+import "b" M qualified as MB
+
+MB.cmp (MA.MkT 1) (MA.MkT 2)
=====================================
testsuite/tests/ghci/prog-mhu008/prog-mhu008.stdout
=====================================
@@ -0,0 +1 @@
+True
=====================================
testsuite/tests/ghci/prog-mhu008/unitA
=====================================
@@ -0,0 +1,5 @@
+-this-unit-id a-0-inplace
+-this-package-name a
+-i
+-ia
+M
=====================================
testsuite/tests/ghci/prog-mhu008/unitB
=====================================
@@ -0,0 +1,6 @@
+-this-unit-id b-0-inplace
+-this-package-name b
+-package-id a-0-inplace
+-i
+-ib
+M
=====================================
testsuite/tests/indexed-types/should_compile/T27828.hs
=====================================
@@ -0,0 +1,50 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+module Bug where
+
+import Data.Functor.Identity (Identity(..))
+import Data.Kind (Type)
+import Data.Proxy (Proxy(..))
+import Data.Type.Equality ((:~:)(..))
+
+type TyFun :: Type -> Type -> Type
+data TyFun a b
+
+type (~>) :: Type -> Type -> Type
+type a ~> b = TyFun a b -> Type
+infixr 0 ~>
+
+type Apply :: (k1 ~> k2) -> k1 -> k2
+type family Apply f x
+
+type Rep1 :: (k -> Type) -> k -> Type
+type family Rep1 f
+
+type To1 :: Rep1 f a -> f a
+type family To1 z
+
+type Par1 :: Type -> Type
+newtype Par1 p = Par1 p
+
+type To1Sym0 :: forall k (f :: k -> Type) (a :: k). Rep1 f a ~> f a
+data To1Sym0 z
+
+applyTo1Sym0 :: forall k (f :: k -> Type) (a :: k) (x :: Rep1 f a). Proxy x -> Apply @(Rep1 f a) @(f a) To1Sym0 x :~: To1 x
+applyTo1Sym0 _ = undefined
+
+type IdentitySym0 :: a ~> Identity a
+data IdentitySym0 z
+type instance Apply IdentitySym0 x = 'Identity x
+
+type Aux :: Rep1 Identity a -> Rep1 Identity a -> Identity a
+type family Aux x y where
+ Aux x ('Par1 wombat) = Apply IdentitySym0 wombat
+
+type instance Rep1 Identity = Par1
+type instance To1 @Identity y = Aux y y
+
+lemma :: forall a (z :: a). Apply @(Rep1 Identity a) @(Identity a) To1Sym0 ('Par1 z) :~: 'Identity z
+lemma = applyTo1Sym0 @Type @Identity @a (Proxy @('Par1 z))
+-- lemma = applyTo1Sym0 @Type @Identity @a @('Par1 z) (Proxy @('Par1 z))
=====================================
testsuite/tests/indexed-types/should_compile/all.T
=====================================
@@ -316,3 +316,4 @@ test('T25611b', normal, compile, [''])
test('T25611c', normal, compile, [''])
test('T25611d', normal, compile, [''])
test('T25657', normal, compile, [''])
+test('T27828', normal, compile, [''])
=====================================
testsuite/tests/primops/should_run/T27299.hs
=====================================
@@ -0,0 +1,23 @@
+{-# LANGUAGE MagicHash #-}
+import GHC.Exts
+import GHC.Word
+import Numeric
+
+main :: IO ()
+main = do
+ putStrLn $ showHex (W# (bitReverse8# 0x55##)) ""
+ putStrLn $ showHex (W# (bitReverse8# 0xAA##)) ""
+ putStrLn $ showHex (W# (bitReverse16# 0x5555##)) ""
+ putStrLn $ showHex (W# (bitReverse16# 0xAAAA##)) ""
+ putStrLn $ showHex (W# (bitReverse32# 0x5555_5555##)) ""
+ putStrLn $ showHex (W# (bitReverse32# 0xAAAA_AAAA##)) ""
+ putStrLn $ showHex (W# (byteSwap16# 0xABCD##)) ""
+ putStrLn $ showHex (W# (byteSwap32# 0xABCD_EF12##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse8# 0x55##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse8# 0xAA##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse16# 0x5555##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse16# 0xAAAA##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse32# 0x5555_5555##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse32# 0xAAAA_AAAA##)) ""
+ putStrLn $ showHex (W# (noinline byteSwap16# 0xABCD##)) ""
+ putStrLn $ showHex (W# (noinline byteSwap32# 0xABCD_EF12##)) ""
=====================================
testsuite/tests/primops/should_run/T27299.stdout
=====================================
@@ -0,0 +1,16 @@
+aa
+55
+aaaa
+5555
+aaaaaaaa
+55555555
+cdab
+12efcdab
+aa
+55
+aaaa
+5555
+aaaaaaaa
+55555555
+cdab
+12efcdab
=====================================
testsuite/tests/primops/should_run/all.T
=====================================
@@ -91,3 +91,4 @@ test('T24496'
]
, compile_and_run, ['-O'])
test('T6026', normal, compile_and_run, [''])
+test('T27299', normal, compile_and_run, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/500bcd9f97f5ff9e157b688bb70101…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/500bcd9f97f5ff9e157b688bb70101…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/jeltsch/improve-closure-property-check] 6 commits: Change the C types of hs_{bitrev,bswap}{16,32} to match the Haskell types
by Wolfgang Jeltsch (@jeltsch) 23 Sep '26
by Wolfgang Jeltsch (@jeltsch) 23 Sep '26
23 Sep '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/improve-closure-property-check at Glasgow Haskell Compiler / GHC
Commits:
545fd4fb by ARATA Mizuki at 2026-09-22T15:03:24-04:00
Change the C types of hs_{bitrev,bswap}{16,32} to match the Haskell types
bitReverse{16,32}# and byteSwap{16,32}# have the type
Word# -> Word#, but their C correspondents took and
returned StgWord{16,32}.
The mismatch on bitReverse16# led to the problem reported
in #27299. Although no similar issue is reported for
bitReverse32# and byteSwap{16,32}#, it seemed wise to
change them proactively.
This commit fixes the mismatch by changing the C type.
Fixes #27299
- - - - -
bf17f289 by fendor at 2026-09-22T15:04:05-04:00
Don't lose instances from shadowed imported modules with the same name
When we look for instances below the current module, we need to check
the unit id as well when we check for whether the module is the current
module, otherwise we ignore modules we import that have the same name as
the import module.
Adds regression test.
- - - - -
e1f26c4d by Wolfgang Jeltsch at 2026-09-23T23:41:39+03:00
Improve the `mhu-closure` makefile
- - - - -
a65a07aa by Wolfgang Jeltsch at 2026-09-23T23:41:39+03:00
Make `ghci-multi` hide all unneeded packages
- - - - -
1343cf0b by Wolfgang Jeltsch at 2026-09-23T23:41:39+03:00
Re-implement the home unit closure check
Compared to the previous implementation, the new one has the following
advantages:
* It is correct.
- It distinguishes between units that have the same unit ID but
different ABI hashes.
- When `-hide-all-packages` is not used, it considers as home unit
dependencies also units that are made implicitly available
because they are in the package database.
* It seems to be faster in usual settings.
- In particular, it does not have a preparation phase in which it
merges the dependency information from all home units, so that
its running time does not grow linearly with the size of the
package database in normal Cabal scenarios.
* It is (hopefully) clearer.
* It is better documented.
- - - - -
aacc2e14 by Wolfgang Jeltsch at 2026-09-23T23:41:39+03:00
Improve the definition of the home unit closure property
- - - - -
24 changed files:
- + changelog.d/26610
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Unit/Env.hs
- hadrian/ghci-multi-cabal.in
- rts/include/stg/Prim.h
- rts/prim/bitrev.c
- rts/prim/bswap.c
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/Makefile
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stderr
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stdout
- + testsuite/tests/ghci/prog-mhu008/Makefile
- + testsuite/tests/ghci/prog-mhu008/a/M.hs
- + testsuite/tests/ghci/prog-mhu008/all.T
- + testsuite/tests/ghci/prog-mhu008/b/M.hs
- + testsuite/tests/ghci/prog-mhu008/prog-mhu008.script
- + testsuite/tests/ghci/prog-mhu008/prog-mhu008.stdout
- + testsuite/tests/ghci/prog-mhu008/unitA
- + testsuite/tests/ghci/prog-mhu008/unitB
- + testsuite/tests/primops/should_run/T27299.hs
- + testsuite/tests/primops/should_run/T27299.stdout
- testsuite/tests/primops/should_run/all.T
Changes:
=====================================
changelog.d/26610
=====================================
@@ -0,0 +1,7 @@
+section: compiler
+synopsis: Fix instance resolution for shadowed modules
+description:
+ Instances imported from modules with the same module name as the importing module
+ were dropped accidentally since we didn't account for the unit id of the imported module.
+mrs: !16648
+issues: #26610
=====================================
compiler/GHC/Driver/Downsweep.hs
=====================================
@@ -6,6 +6,8 @@
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ViewPatterns #-}
+{-# OPTIONS_GHC -Wno-invalid-haddock #-}
+
-- | See Note [The ModuleGraph]
module GHC.Driver.Downsweep
( downsweep
@@ -54,7 +56,6 @@ import GHC.Runtime.Context
import Language.Haskell.Syntax.ImpExp
import GHC.Types.UnresolvedImport
-import GHC.Data.Graph.Directed
import GHC.Data.FastString
import GHC.Data.Maybe ( expectJust )
import qualified GHC.Data.Maybe as M
@@ -71,12 +72,15 @@ import GHC.Utils.Logger
import GHC.Utils.Fingerprint
import GHC.Utils.TmpFs
import GHC.Utils.Constants
+import GHC.Utils.Monad (concatMapM)
+import GHC.Utils.Monad.State.Strict
import GHC.Types.Error
import GHC.Types.Target
import GHC.Types.SourceFile
import GHC.Types.SourceError
import GHC.Types.SrcLoc
+import GHC.Types.Unique.Set
import GHC.Types.Unique.Map
import GHC.Types.PkgQual
import GHC.Types.Basic
@@ -91,9 +95,12 @@ import GHC.Unit.Module.Graph
import GHC.Unit.Module.Deps
import qualified GHC.Unit.Home.Graph as HUG
import GHC.Unit.Module.Stage
+import GHC.Unit.External.Index (UnitAbiHash)
import Data.Either ( partitionEithers, lefts )
+import Data.Map (Map)
import qualified Data.Map as Map
+import Data.Set (Set)
import qualified Data.Set as Set
import Control.Concurrent.MVar
@@ -101,7 +108,7 @@ import Control.Monad
import Control.Monad.Trans.Except ( ExceptT(..), runExceptT, throwE )
import qualified Control.Monad.Catch as MC
import Data.Maybe
-import Data.List (partition)
+import Data.List (sort, partition)
import Data.Time
import Data.List (unfoldr)
import Data.Bifunctor (first, bimap)
@@ -933,52 +940,175 @@ rootSummariesParallel n_jobs hsc_env diag_wrapper msg get_summary = do
-- * Check/validate properties and error out
--------------------------------------------------------------------------------
--- | This function checks then important property that if both p and q are home units
--- then any dependency of p, which transitively depends on q is also a home unit.
+-- | Checks whether the given 'UnitEnv' has the closure property.
--
--- See Note [Multiple Home Units], section 'Closure Property'.
-checkHomeUnitsClosed :: UnitEnv -> [DriverMessages]
-checkHomeUnitsClosed ue
- | Set.null bad_unit_ids = []
- | otherwise = [singleMessage $ mkPlainErrorMsgEnvelope rootLoc $ DriverHomePackagesNotClosed (Set.toList bad_unit_ids)]
+-- See the section “Closure Property” in @Note [Multiple Home Units]@ for the
+-- definition of the closure property and
+-- @Note [Home unit closure property check]@ below for a discussion of the
+-- algorithm used for this check, its justification, and a potential
+-- alternative.
+checkHomeUnitsClosed :: UnitEnv -> [DriverMessages]
+checkHomeUnitsClosed unit_env
+ | null offenders = []
+ | otherwise = [
+ singleMessage $
+ mkPlainErrorMsgEnvelope error_source_span $
+ DriverHomePackagesNotClosed (sort offenders)
+ ]
where
- home_id_set = HUG.allUnits $ ue_home_unit_graph ue
- bad_unit_ids = upwards_closure Set.\\ home_id_set {- Remove all home units reached, keep only bad nodes -}
- rootLoc = mkGeneralSrcSpan (fsLit "<command line>")
- downwards_closure :: Graph (Node UnitId UnitId)
- downwards_closure = graphFromEdgedVerticesUniq graphNodes
+ -- | The 'UnitId' and 'HomeUnitEnv' of each home unit.
+ home_unit_data :: [(UnitId, HomeUnitEnv)]
+ home_unit_data = HUG.unitEnv_assocs (ue_home_unit_graph unit_env)
+
+ -- | The 'UnitId's of all home units.
+ home_units :: UniqSet UnitId
+ home_units = mkUniqSet (map fst home_unit_data)
+
+ -- | All offending dependencies. A dependency of a unit /u/ on a unit /v/ is
+ -- offending exactly if /u/ is an external unit reachable from a home unit
+ -- and /v/ is a home unit. Each such dependency is represented in this list
+ -- by the pair of the 'UnitId' of /u/ and the 'UnitId' of /v/.
+ offenders :: [(UnitId, UnitId)]
+ offenders
+ = evalState (collect (map (homeUnitEnv_units . snd) home_unit_data))
+ emptyUniqMap
+ where
- inverse_closure = graphReachability $ transposeG downwards_closure
+ -- | Collects offending dependencies.
+ collect :: [UnitState]
+ -- ^ The 'UnitState's of the home units from which to traverse
+ -- the dependency graph.
+ -> State (UniqMap UnitId (Set UnitAbiHash)) [(UnitId, UnitId)]
+ -- ^ A stateful computation that collects offending dependencies
+ -- that have not yet been found. It uses its state, which is an
+ -- efficent representation of a set of 'GlobalUnitKey's, to
+ -- keep track of which units have already been considered as
+ -- sources of offending dependencies.
+ collect = concatMapM $ \ unit_state ->
+ collect_for_home_unit
+ (unitInfoMap unit_state)
+ (map (toUnitId . fst) $ explicitUnits $ unit_state)
+ where
- upwards_closure = Set.fromList $ map node_key $ allReachableMany inverse_closure [DigraphNode uid uid [] | uid <- Set.toList home_id_set]
+ -- | Collects offending dependencies that are reachable from a particular
+ -- home unit.
+ collect_for_home_unit
+ :: UnitInfoMap
+ -- ^ The 'UnitInfoMap' of the home unit.
+ -> [UnitId]
+ -- ^ The 'UnitId's of the units from which to traverse the dependency
+ -- graph.
+ -> State (UniqMap UnitId (Set UnitAbiHash)) [(UnitId, UnitId)]
+ -- ^ A stateful computation that collects offending dependencies that
+ -- have not yet been found. It uses its state, which is an efficent
+ -- representation of a set of 'GlobalUnitKey's, to keep track of
+ -- which units have already been considered as sources of offending
+ -- dependencies.
+ collect_for_home_unit _ []
+ = return []
+ collect_for_home_unit unit_info_map (current_unit : remaining_units) = do
+ let
+
+ -- | The 'UnitInfo' of the current unit.
+ unit_info :: UnitInfo
+ unit_info
+ = fromMaybe (pprPanic unit_not_found_msg (ppr current_unit)) $
+ lookupUniqMap unit_info_map current_unit
+ where
+
+ -- | The message that says that a unit was not found.
+ unit_not_found_msg :: String
+ unit_not_found_msg = "Unit not found during closure property check"
+
+ -- | The ABI hash of the current unit.
+ unit_abi_hash :: UnitAbiHash
+ unit_abi_hash = unitAbiHash unit_info
+
+ has_been_processed <- gets $ maybe False (Set.member unit_abi_hash) .
+ (`lookupUniqMap` current_unit)
+ if has_been_processed
+ then collect_for_home_unit unit_info_map remaining_units
+ else do
+ modify $ \ processed -> addToUniqMap_C Set.union
+ processed
+ current_unit
+ (Set.singleton unit_abi_hash)
+ let
+
+ -- | The 'UnitId's of the units that the current unit depends on.
+ needed_units :: [UnitId]
+ needed_units = unitDepends unit_info
+
+ -- | The offending dependencies of the current unit.
+ current_offenders :: [(UnitId, UnitId)]
+ current_offenders
+ | current_unit `elementOfUniqSet` home_units
+ = []
+ | otherwise
+ = map ((,) current_unit) $
+ nonDetEltsUniqSet $
+ mkUniqSet needed_units `intersectUniqSets` home_units
+
+ remaining_offenders <- collect_for_home_unit unit_info_map $
+ needed_units ++ remaining_units
+ return $ current_offenders ++ remaining_offenders
+
+ -- | A fake source span used for reporting violations of the closure property.
+ error_source_span :: SrcSpan
+ error_source_span = mkGeneralSrcSpan (fsLit "<command line>")
- all_unit_direct_deps :: UniqMap UnitId (Set.Set UnitId)
- all_unit_direct_deps
- = HUG.unitEnv_foldWithKey go emptyUniqMap $ ue_home_unit_graph ue
- where
- go rest this this_uis =
- plusUniqMap_C Set.union
- (addToUniqMap_C Set.union external_depends this (Set.fromList $ this_deps))
- rest
- where
- external_depends = mapUniqMap (Set.fromList . unitDepends) (unitInfoMap this_units)
- this_units = homeUnitEnv_units this_uis
- this_deps = [ toUnitId unit | (unit,Just _) <- explicitUnits this_units]
-
- graphNodes :: [Node UnitId UnitId]
- graphNodes = go Set.empty home_id_set
- where
- go done todo
- = case Set.minView todo of
- Nothing -> []
- Just (uid, todo')
- | Set.member uid done -> go done todo'
- | otherwise -> case lookupUniqMap all_unit_direct_deps uid of
- Nothing -> pprPanic "uid not found" (ppr (uid, all_unit_direct_deps))
- Just depends ->
- let todo'' = (depends Set.\\ done) `Set.union` todo'
- in DigraphNode uid uid (Set.toList depends) : go (Set.insert uid done) todo''
+{-
+
+Note [Home unit closure property check]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Per the definition in Note [Multiple Home Units], a unit environment has the
+closure property exactly if there are no paths /h/₁ →* /e/ →* /h/₂ in the
+dependency graph, where /h/₁ and /h/₂ are home units and /e/ is an external
+unit. However, the algorithm used by 'checkHomeUnitsClosed' searches for
+so-called offending dependencies, which are dependencies /e/ → /h/₂ that are
+part of a path /h/₁ →* /e/ → /h/₂ in the dependency graph. To see that this is a
+viable approach, consider the following:
+
+ * A path /h/₁ →* /e/ → /h/₂ is also a path /h/₁ →* /e/ →* /h/₂.
+
+ * For each path /h/₁ →* /e/ →* /h/₂, there exists a path /h/₁ →* /e/′ → /h/₂′,
+ where /e/′ is an external unit and /h/₂′ is a home unit. Such a path can be
+ constructed by taking as /h/₂′ the first home unit on the path /e/ →* /h/₂
+ and as /e/′ the, necessarily external, unit preceding it.
+
+Concretely, the algorithm picks one home unit after the other, determines what
+units it directly depends on, and, starting from them, follows unit dependencies
+to search for offending dependencies. It does not follow dependencies that have
+been followed before, possibly when processing another home unit. To achieve
+this, the algorithm tracks, across home units, from which units it has already
+followed dependencies. For this tracking, it identifies each unit by a 'UnitId'
+and an ABI hash. Using only a 'UnitId' would not work, because 'UnitId's are not
+always globally unique. Also using only an ABI hash is not an option, because an
+ABI hash is not necessarily an ABI hash: it can also be the string @"inline"@.
+
+The correctness of this algorithm rests on the, likely correct, assumption that,
+among the units mentioned in the 'UnitState' of a particular home unit, any unit
+can be uniquely identified by its 'UnitId' and thus 'UnitId' clashes can only
+occur across the 'UnitState's of different home units.
+
+An alternative approach to finding offending dependencies would be to follow
+dependencies starting from all units that /any/ home unit directly depends on
+instead of considering the different home units separately. A corresponding
+algorithm could in principle find the dependencies of a particular unit
+independently of any home unit by fetching the 'UnitInfo' of that unit from the
+'GlobalUnitInfoMap'. However, for such a lookup the algorithm would need not
+only the 'UnitId' but also the ABI hash of the unit in question. Therefore,
+whenever following a dependency of a unit /u/ on a unit /v/, it would have to
+determine the ABI hash of /v/, so that it could later look up /v/’s
+dependencies. The ABI hashes of all units that /u/ depends on should be
+available in the 'unitAbiDepends' field of /u/’s 'UnitInfo'. However, at the
+time of writing, 'unitAbiDepends' never contained anything other than the empty
+list during GHC test runs, which indicated that this alternative solution was
+impossible to realize.
+
+-}
--------------------------------------------------------------------------------
-- * Enable Code Gen for Template Haskell
@@ -1763,7 +1893,7 @@ data NodeRes v
--
-- See also Note [Downsweep Control Flow and Caching]
dfsBuild :: (Ord k, Monad m)
- => Maybe (Map.Map k (NodeRes v))
+ => Maybe (Map k (NodeRes v))
-- ^ Base map, existing results. We won't re-expand any of the nodes
-- already present in this map.
-> [n]
@@ -1773,7 +1903,7 @@ dfsBuild :: (Ord k, Monad m)
-> (n -> m (NodeRes (v,[n])))
-- ^ Expand this node into its payload result and into the list of
-- children nodes to visit next.
- -> m (Map.Map k (NodeRes v))
+ -> m (Map k (NodeRes v))
-- ^ The result accumulates the payload of expanding the root nodes
-- and all nodes transitively reachable from those roots.
dfsBuild base_map roots key expand = go roots (fromMaybe Map.empty base_map)
=====================================
compiler/GHC/Driver/Env.hs
=====================================
@@ -263,13 +263,13 @@ hugCompleteSigsBelow hsc uid mn = foldr (++) [] <$>
-- | Find instances visible from the given set of imports
hugInstancesBelow :: HscEnv -> UnitId -> ModuleNameWithIsBoot -> IO (InstEnv, [FamInst])
hugInstancesBelow hsc_env uid mnwib = do
- let mn = gwib_mod mnwib
+ let mn = mkModule uid (gwib_mod mnwib)
(insts, famInsts) <-
unzip . concat <$>
hugSomeThingsBelowUs (\mod_info ->
let details = hm_details mod_info
-- Don't include instances for the current module
- in if moduleName (mi_module (hm_iface mod_info)) == mn
+ in if fmap toUnitId (mi_module (hm_iface mod_info)) == mn
then []
else [(md_insts details, md_fam_insts details)])
True -- Include -hi-boot
=====================================
compiler/GHC/Driver/Errors/Ppr.hs
=====================================
@@ -235,10 +235,17 @@ instance Diagnostic DriverMessage where
"but no output will be generated.") $$
(text "There is no module named" <+>
quotes (ppr mod_name) <> text "."))
- DriverHomePackagesNotClosed needed_unit_ids
- -> mkSimpleDecorated $ vcat ([text "Home units are not closed."
- , text "It is necessary to also load the following units:" ]
- ++ map (\uid -> text "-" <+> ppr uid) needed_unit_ids)
+ DriverHomePackagesNotClosed offending_dependencies
+ -> mkSimpleDecorated $
+ hang (text "Some units are not loaded but depend on loaded units.")
+ 4
+ (vcat (map pprDependency offending_dependencies))
+ where
+
+ pprDependency :: (UnitId, UnitId) -> SDoc
+ pprDependency (external_unit, home_unit)
+ = ppr external_unit <+> arrow <+> ppr home_unit
+
DriverInterfaceError reason -> diagnosticMessage (ifaceDiagnosticOpts opts) reason
DriverInconsistentDynFlags msg
=====================================
compiler/GHC/Driver/Errors/Types.hs
=====================================
@@ -369,7 +369,7 @@ data DriverMessage where
DriverRedirectedNoMain :: !ModuleName -> DriverMessage
- DriverHomePackagesNotClosed :: ![UnitId] -> DriverMessage
+ DriverHomePackagesNotClosed :: ![(UnitId, UnitId)] -> DriverMessage
DriverInterfaceError :: !IfaceMessage -> DriverMessage
=====================================
compiler/GHC/Unit/Env.hs
=====================================
@@ -443,13 +443,14 @@ The flow:
Closure Property
----------------
-You must perform a clean cut of the dependency graph.
+A unit environment must have the closure property:
-> Any dependency which is not a home unit must not (transitively) depend on a home unit.
+ No used external unit depends on a home unit.
-For example, if you have three packages p, q and r, then if p depends on q which
-depends on r then it is illegal to load both p and r as home units but not q,
-because q is a dependency of the home unit p which depends on another home unit r.
+More concretely, a unit environment has the closure property exactly if no home
+unit directly or indirectly depends on an external unit that directly or
+indirectly depends on a home unit. 'GHC.Driver.Downsweep.checkHomeUnitsClosed'
+checks whether a given unit environment indeed has this property.
Offsetting Paths
----------------
=====================================
hadrian/ghci-multi-cabal.in
=====================================
@@ -10,4 +10,4 @@ export TOOL_OUTPUT=.hadrian_ghci_multi/ghci_args
# Replace newlines with spaces, as these otherwise break the ghci invocation on windows.
CABFLAGS=-v0 "hadrian/build-cabal" multi --build-root=.hadrian_ghci_multi --flavour=ghc-in-ghci $HADRIAN_ARGS
GHC_FLAGS="$GHC_FLAGS $(cat $TOOL_OUTPUT | tr '\n\r' ' ')"
-$RUN_GHC --interactive $GHC_FLAGS $@ -fno-code -fwrite-interface -O0 +RTS -A128m
+$RUN_GHC --interactive $GHC_FLAGS $@ -hide-all-packages -fno-code -fwrite-interface -O0 +RTS -A128m
=====================================
rts/include/stg/Prim.h
=====================================
@@ -59,16 +59,16 @@ StgWord hs_xchg32(StgWord x, StgWord val);
StgWord64 hs_xchg64(StgWord x, StgWord64 val);
/* rts/prim/bswap.c */
-StgWord16 hs_bswap16(StgWord16 x);
-StgWord32 hs_bswap32(StgWord32 x);
+StgWord hs_bswap16(StgWord x);
+StgWord hs_bswap32(StgWord x);
StgWord64 hs_bswap64(StgWord64 x);
/* rts/prim/bitrev.c
This was done as part of issue #16164.
See Note [Bit reversal primop] for more details about the implementation.*/
StgWord hs_bitrev8(StgWord x);
-StgWord16 hs_bitrev16(StgWord16 x);
-StgWord32 hs_bitrev32(StgWord32 x);
+StgWord hs_bitrev16(StgWord x);
+StgWord hs_bitrev32(StgWord x);
StgWord64 hs_bitrev64(StgWord64 x);
/* rts/prim/longlong.c */
=====================================
rts/prim/bitrev.c
=====================================
@@ -36,8 +36,8 @@ hs_bitrev8(StgWord x)
return x;
}
-StgWord16
-hs_bitrev16(StgWord16 x)
+StgWord
+hs_bitrev16(StgWord x)
{
x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1 );
x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2 );
@@ -46,14 +46,14 @@ hs_bitrev16(StgWord16 x)
return x;
}
-StgWord32
-hs_bitrev32(StgWord32 x)
+StgWord
+hs_bitrev32(StgWord x)
{
- x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1 );
- x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2 );
- x = ((x >> 4) & 0x0F0F0F0F) | ((x & 0x0F0F0F0F) << 4 );
- x = ((x >> 8) & 0x00FF00FF) | ((x & 0x00FF00FF) << 8 );
- x = ( x >> 16 ) | ( x << 16 );
+ x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1 );
+ x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2 );
+ x = ((x >> 4) & 0x0F0F0F0F) | ((x & 0x0F0F0F0F) << 4 );
+ x = ((x >> 8) & 0x00FF00FF) | ((x & 0x00FF00FF) << 8 );
+ x = ((x >> 16) & 0x0000FFFF) | ((x & 0x0000FFFF) << 16);
return x;
}
=====================================
rts/prim/bswap.c
=====================================
@@ -1,16 +1,18 @@
#include "Rts.h"
-StgWord16
-hs_bswap16(StgWord16 x)
+StgWord
+hs_bswap16(StgWord x)
{
- return ((x >> 8) | (x << 8));
+ x = (StgWord16)x;
+ return (StgWord16)((x >> 8) | (x << 8));
}
-StgWord32
-hs_bswap32(StgWord32 x)
+StgWord
+hs_bswap32(StgWord x)
{
- return ((x >> 24) | ((x >> 8) & 0xff00) |
- (x << 24) | ((x & 0xff00) << 8));
+ x = (StgWord32)x;
+ return (StgWord32)((x >> 24) | ((x >> 8) & 0xff00) |
+ (x << 24) | ((x & 0xff00) << 8));
}
StgWord64
=====================================
testsuite/tests/driver/multipleHomeUnits/mhu-closure/Makefile
=====================================
@@ -3,39 +3,47 @@ include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/test.mk
SETUP=../Setup -v0
+CONFIGURE=configure \
+ $(CABAL_MINIMAL_BUILD) \
+ --with-ghc='$(TEST_HC)' \
+ --with-hc-pkg='$(GHC_PKG)' \
+ --ghc-options='$(TEST_HC_OPTS)' \
+ --package-db=../tmp.d
+TEST_BUILD='$(TEST_HC)' $(TEST_HC_OPTS) -fhide-source-paths -fforce-recomp
+ONLY_BASE=-hide-all-packages -package base
-mhu-closure: clean
- $(MAKE) -s --no-print-directory clean
+mhu-closure: clean pkg-database
+ ! $(TEST_BUILD) -unit @unitP
+ ! $(TEST_BUILD) -unit @unitP -unit @unitQ
+ ! $(TEST_BUILD) -unit @unitP -unit @unitR
+ ! $(TEST_BUILD) -unit @unitP -unit @unitR1
+ $(TEST_BUILD) -unit @unitP -unit @unitQ -unit @unitR
+ ! $(TEST_BUILD) -unit @unitP -unit @unitQ -unit @unitR1
+ $(TEST_BUILD) $(ONLY_BASE) -unit @unitP
+ $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitQ
+ ! $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitR
+ ! $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitR1
+ $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitQ -unit @unitR
+ $(TEST_BUILD) $(ONLY_BASE) -unit @unitP -unit @unitQ -unit @unitR1
+
+.PHONY: pkg-database
+pkg-database:
'$(GHC_PKG)' init tmp.d
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 --make Setup
- cd p && $(SETUP) clean
- cd p && $(SETUP) configure $(CABAL_MINIMAL_BUILD) --ipid=p-0.1.0.0 --with-ghc='$(TEST_HC)' --with-hc-pkg='$(GHC_PKG)' --ghc-options='$(TEST_HC_OPTS)' --package-db=../tmp.d
+ cd p && $(SETUP) $(CONFIGURE) --ipid=p-0.1.0.0
cd p && $(SETUP) build
cd p && $(SETUP) register --inplace
- cd q && $(SETUP) configure $(CABAL_MINIMAL_BUILD) --ipid=q-0.1.0.0 --with-ghc='$(TEST_HC)' --with-hc-pkg='$(GHC_PKG)' --ghc-options='$(TEST_HC_OPTS)' --package-db=../tmp.d
+ cd q && $(SETUP) $(CONFIGURE) --ipid=q-0.1.0.0
cd q && $(SETUP) build
cd q && $(SETUP) register --inplace
- cd r && $(SETUP) configure $(CABAL_MINIMAL_BUILD) --ipid=r-0.1.0.0 --with-ghc='$(TEST_HC)' --with-hc-pkg='$(GHC_PKG)' --ghc-options='$(TEST_HC_OPTS)' --package-db=../tmp.d
+ cd r && $(SETUP) $(CONFIGURE) --ipid=r-0.1.0.0
cd r && $(SETUP) build
cd r && $(SETUP) register --inplace
- # This should work
- '$(TEST_HC)' $(TEST_HC_OPTS) -fhide-source-paths -fforce-recomp -unit @unitP
- # So should this
- '$(TEST_HC)' $(TEST_HC_OPTS) -fhide-source-paths -fforce-recomp -unit @unitP -unit @unitQ
- # So should this
- '$(TEST_HC)' $(TEST_HC_OPTS) -fhide-source-paths -fforce-recomp -unit @unitP -unit @unitQ -unit @unitR
- # This should error with a closure message
- ! '$(TEST_HC)' $(TEST_HC_OPTS) -fhide-source-paths -fforce-recomp -unit @unitP -unit @unitR
- # This should work, even though r1 is not in the package db
- '$(TEST_HC)' $(TEST_HC_OPTS) -fhide-source-paths -fforce-recomp -unit @unitP -unit @unitQ -unit @unitR1
- # This should fail, even though r1 is not in the package db
- ! '$(TEST_HC)' $(TEST_HC_OPTS) -fhide-source-paths -fforce-recomp -unit @unitP -unit @unitR1
+.PHONY: clean
+clean:
+ $(RM) -r tmp.d Setup$(exeext) */dist* *.hi *.o */*.hi */*.o
ifeq "$(CLEANUP)" "1"
$(MAKE) -s --no-print-directory clean
endif
-
-clean :
- $(RM) -r tmp*.d inst-* *.o *.hi */*.o */*.hi */Setup$(exeext) */dist Setup$(exeext)
-
=====================================
testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stderr
=====================================
@@ -1,10 +1,28 @@
<command line>: error: [GHC-03271]
- Home units are not closed.
- It is necessary to also load the following units:
- - q-0.1.0.0
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
<command line>: error: [GHC-03271]
- Home units are not closed.
- It is necessary to also load the following units:
- - q-0.1.0.0
+ Some units are not loaded but depend on loaded units.
+ r-0.1.0.0 -> q-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ r-0.1.0.0 -> q-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
+
+<command line>: error: [GHC-03271]
+ Some units are not loaded but depend on loaded units.
+ q-0.1.0.0 -> p-0.1.0.0
=====================================
testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stdout
=====================================
@@ -1,3 +1,6 @@
+[1 of 3] Compiling P[p-0.1.0.0]
+[2 of 3] Compiling Q[q-0.1.0.0]
+[3 of 3] Compiling R[r-0.1.0.0]
[1 of 1] Compiling P
[1 of 2] Compiling P[p-0.1.0.0]
[2 of 2] Compiling Q[q-0.1.0.0]
=====================================
testsuite/tests/ghci/prog-mhu008/Makefile
=====================================
@@ -0,0 +1,3 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
=====================================
testsuite/tests/ghci/prog-mhu008/a/M.hs
=====================================
@@ -0,0 +1,4 @@
+module M (T (..)) where
+
+newtype T = MkT Int
+ deriving (Eq, Ord)
=====================================
testsuite/tests/ghci/prog-mhu008/all.T
=====================================
@@ -0,0 +1,5 @@
+test('prog-mhu008',
+ [extra_files(['a/', 'b/', 'unitA', 'unitB']),
+ cmd_prefix('ghciWayFlags=' + config.ghci_way_flags),
+ req_interp],
+ ghci_multiunit_script, [['unitA', 'unitB'], 'prog-mhu008.script'])
=====================================
testsuite/tests/ghci/prog-mhu008/b/M.hs
=====================================
@@ -0,0 +1,11 @@
+{-# LANGUAGE PackageImports #-}
+
+module M
+ ( module Export
+ , cmp
+ ) where
+
+import "a" M as Export
+
+cmp :: T -> T -> Bool
+cmp x y = x <= y
=====================================
testsuite/tests/ghci/prog-mhu008/prog-mhu008.script
=====================================
@@ -0,0 +1,5 @@
+:set -XPackageImports
+import "a" M qualified as MA
+import "b" M qualified as MB
+
+MB.cmp (MA.MkT 1) (MA.MkT 2)
=====================================
testsuite/tests/ghci/prog-mhu008/prog-mhu008.stdout
=====================================
@@ -0,0 +1 @@
+True
=====================================
testsuite/tests/ghci/prog-mhu008/unitA
=====================================
@@ -0,0 +1,5 @@
+-this-unit-id a-0-inplace
+-this-package-name a
+-i
+-ia
+M
=====================================
testsuite/tests/ghci/prog-mhu008/unitB
=====================================
@@ -0,0 +1,6 @@
+-this-unit-id b-0-inplace
+-this-package-name b
+-package-id a-0-inplace
+-i
+-ib
+M
=====================================
testsuite/tests/primops/should_run/T27299.hs
=====================================
@@ -0,0 +1,23 @@
+{-# LANGUAGE MagicHash #-}
+import GHC.Exts
+import GHC.Word
+import Numeric
+
+main :: IO ()
+main = do
+ putStrLn $ showHex (W# (bitReverse8# 0x55##)) ""
+ putStrLn $ showHex (W# (bitReverse8# 0xAA##)) ""
+ putStrLn $ showHex (W# (bitReverse16# 0x5555##)) ""
+ putStrLn $ showHex (W# (bitReverse16# 0xAAAA##)) ""
+ putStrLn $ showHex (W# (bitReverse32# 0x5555_5555##)) ""
+ putStrLn $ showHex (W# (bitReverse32# 0xAAAA_AAAA##)) ""
+ putStrLn $ showHex (W# (byteSwap16# 0xABCD##)) ""
+ putStrLn $ showHex (W# (byteSwap32# 0xABCD_EF12##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse8# 0x55##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse8# 0xAA##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse16# 0x5555##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse16# 0xAAAA##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse32# 0x5555_5555##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse32# 0xAAAA_AAAA##)) ""
+ putStrLn $ showHex (W# (noinline byteSwap16# 0xABCD##)) ""
+ putStrLn $ showHex (W# (noinline byteSwap32# 0xABCD_EF12##)) ""
=====================================
testsuite/tests/primops/should_run/T27299.stdout
=====================================
@@ -0,0 +1,16 @@
+aa
+55
+aaaa
+5555
+aaaaaaaa
+55555555
+cdab
+12efcdab
+aa
+55
+aaaa
+5555
+aaaaaaaa
+55555555
+cdab
+12efcdab
=====================================
testsuite/tests/primops/should_run/all.T
=====================================
@@ -91,3 +91,4 @@ test('T24496'
]
, compile_and_run, ['-O'])
test('T6026', normal, compile_and_run, [''])
+test('T27299', normal, compile_and_run, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/db612ab3a3809cbd7c53526cd9d580…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/db612ab3a3809cbd7c53526cd9d580…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
Rodrigo Mesquita pushed to branch wip/romes/hsmodulename at Glasgow Haskell Compiler / GHC
Commits:
0c603dbe by Rodrigo Mesquita at 2026-09-23T17:32:20+01:00
fixes
- - - - -
1 changed file:
- compiler/GHC/Parser/Lexer.x
Changes:
=====================================
compiler/GHC/Parser/Lexer.x
=====================================
@@ -140,7 +140,6 @@ import GHC.Parser.Errors.Ppr ()
import GHC.Parser.Lexer.Interface
import qualified GHC.Parser.Lexer.String as Lexer.String
import GHC.Parser.String
-import GHC.Unit.Module.Name (ModuleName(..))
}
-- -----------------------------------------------------------------------------
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0c603dbebc167a3520efe67867734c6…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0c603dbebc167a3520efe67867734c6…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/apk/expose-overloaded-unfoldings] Enable -fexpose-overloaded-unfoldings by default when optimizations are on.
by Andreas Klebinger (@AndreasK) 23 Sep '26
by Andreas Klebinger (@AndreasK) 23 Sep '26
23 Sep '26
Andreas Klebinger pushed to branch wip/apk/expose-overloaded-unfoldings at Glasgow Haskell Compiler / GHC
Commits:
68a44e8f by Andreas Klebinger at 2026-09-23T17:52:34+02:00
Enable -fexpose-overloaded-unfoldings by default when optimizations are on.
I also made the -fexpose-*-unfoldings flags optimization flags rather
than codeGen flags. This was needed to fix a test and is the correct
place for them.
Performance numbers:
In general this averages out to ~1% more file size across the GHC build.
Compiler allocations grow by 0.14% on nofib as the compiler needs to deal with more available unfoldings.
On the cabal test it's awash. With some configurations getting slightly faster, some slightly slower.
It's all in the +/- 0.2% range.
On nofib itself we produce exactly the same code. Which is expected, as it doesn't use -fspecialize-aggresively
anywhere afaik which is needed to take advantage of cross module
specialization.
Fixes #13090
- - - - -
6 changed files:
- + changelog.d/T13090-expose-overloaded-unfoldings
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Iface/Tidy.hs
- docs/users_guide/using-optimisation.rst
- testsuite/tests/dmdanal/should_compile/T23398.stderr
Changes:
=====================================
changelog.d/T13090-expose-overloaded-unfoldings
=====================================
@@ -0,0 +1,6 @@
+section: compiler
+issues: #13090
+mrs: !16684
+synopsis:
+ Enable :ghc-flag:`-fexpose-overloaded-unfoldings` by default with :ghc-flag:`-O` or higher.
+
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -1337,6 +1337,7 @@ optLevelFlags -- see Note [Documenting optimisation flags]
, ([1,2], Opt_Specialise)
, ([1,2], Opt_PolymorphicSpecialisation) -- Now on by default (#23559)
, ([1,2], Opt_CrossModuleSpecialise)
+ , ([1,2], Opt_ExposeOverloadedUnfoldings) -- See Note [Exposing overloaded functions] in GHC.Iface.Tidy
, ([1,2], Opt_InlineGenerics)
, ([1,2], Opt_Strictness)
, ([1,2], Opt_UnboxSmallStrictFields)
=====================================
compiler/GHC/Driver/Flags.hs
=====================================
@@ -971,6 +971,8 @@ optimisationFlags = EnumSet.fromList
, Opt_SolveConstantDicts
, Opt_SpecEval
, Opt_SpecEvalDictFun
+ , Opt_ExposeAllUnfoldings
+ , Opt_ExposeOverloadedUnfoldings
]
-- | The set of flags which affect code generation and can change a program's
@@ -1001,8 +1003,6 @@ codeGenFlags = EnumSet.fromList
, Opt_OmitYields
-- Flags that affect generated code
- , Opt_ExposeAllUnfoldings
- , Opt_ExposeOverloadedUnfoldings
, Opt_NoTypeableBinds
, Opt_NoBuiltinRules
, Opt_NoBignumRules
=====================================
compiler/GHC/Iface/Tidy.hs
=====================================
@@ -806,8 +806,19 @@ anyway we allow for some false positives and simply expose all functions which
have a constraint. This means we might expose more unhelpful unfoldings. But
it seems like the better choice.
-Currently this option is off by default and has to be enabled manually. But
-we might change this in the future.
+We enable the flag by default with -O/O2 to allow users to opt into specialization
+at call sites. We do not enable -fspecialize-aggressively. See also #13090.
+
+In terms of performance impact the cost is very modest:
+On GHC and it's boot libraries overall enabling this flag increases overall disk
+space used by ~1%. With a highly variant distribution across various .hi files.
+In terms of compile times the overhead is low enough to be hard to measure, but
+seemed to be less than 0.2% if anything at all.
+
+It seems tempting to do the same for -fspecialize-aggressively, but that comes in
+at a hefty 20% compile time overhead. So we only provide the unfoldings and leave
+the choice of how much specialization to enable up to the user.
+
-}
{-
=====================================
docs/users_guide/using-optimisation.rst
=====================================
@@ -624,10 +624,10 @@ as such you shouldn't need to set any of them explicitly. A flag
:reverse: -fno-expose-overloaded-unfoldings
:category:
- :default: off
+ :default: -O and above
:since: 9.12.1
- This experimental flag is a slightly less heavy weight alternative
+ This flag is a slightly less heavy weight alternative
to :ghc-flag:`-fexpose-all-unfoldings`.
Instead of exposing all functions it exposes only those functions which
=====================================
testsuite/tests/dmdanal/should_compile/T23398.stderr
=====================================
@@ -40,7 +40,9 @@ T23398.$wbar [InlPrag=[2], Occ=LoopBreaker]
[GblId[StrictWorker([~, !])],
Arity=4,
Str=<L><SP(A,SC(S,L),A)><1L><L>,
- Unf=OtherCon []]
+ Unf=Unf{Src=<vanilla>, TopLvl=True,
+ Value=True, ConLike=True, WorkFree=True, Expandable=True,
+ Guidance=IF_ARGS [0 90 60 0] 91 70}]
T23398.$wbar
= \ (@a)
(@b)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/68a44e8f05c49a8a1b960191af399f7…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/68a44e8f05c49a8a1b960191af399f7…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/clc-proposal-442] 6 commits: Change the C types of hs_{bitrev,bswap}{16,32} to match the Haskell types
by BinderDavid (@BinderDavid) 23 Sep '26
by BinderDavid (@BinderDavid) 23 Sep '26
23 Sep '26
BinderDavid pushed to branch wip/clc-proposal-442 at Glasgow Haskell Compiler / GHC
Commits:
545fd4fb by ARATA Mizuki at 2026-09-22T15:03:24-04:00
Change the C types of hs_{bitrev,bswap}{16,32} to match the Haskell types
bitReverse{16,32}# and byteSwap{16,32}# have the type
Word# -> Word#, but their C correspondents took and
returned StgWord{16,32}.
The mismatch on bitReverse16# led to the problem reported
in #27299. Although no similar issue is reported for
bitReverse32# and byteSwap{16,32}#, it seemed wise to
change them proactively.
This commit fixes the mismatch by changing the C type.
Fixes #27299
- - - - -
bf17f289 by fendor at 2026-09-22T15:04:05-04:00
Don't lose instances from shadowed imported modules with the same name
When we look for instances below the current module, we need to check
the unit id as well when we check for whether the module is the current
module, otherwise we ignore modules we import that have the same name as
the import module.
Adds regression test.
- - - - -
b930a64d by David Binder at 2026-09-23T15:47:51+00:00
Implement CLC proposal #442
Expose `data Unit` and `data TupleN` (for N from 2 to 64) from
module `Data.Tuple`.
- - - - -
ad376f33 by David Binder at 2026-09-23T15:47:51+00:00
Update expected error message in testcase T25180
The testcase T25180 checks for the error messages when
the file is compiled with the options:
'-fdefer-type-errors -fno-max-valid-hole-fits'
- - - - -
187fdad1 by David Binder at 2026-09-23T15:47:51+00:00
Fix expected output in testsuite of haddock
- - - - -
c0cb03d0 by David Binder at 2026-09-23T15:47:51+00:00
Add entry to changelog.d
- - - - -
25 changed files:
- + changelog.d/26610
- + changelog.d/clc-442
- compiler/GHC/Driver/Env.hs
- libraries/base/changelog.md
- libraries/base/src/Data/Tuple.hs
- rts/include/stg/Prim.h
- rts/prim/bitrev.c
- rts/prim/bswap.c
- + testsuite/tests/ghci/prog-mhu008/Makefile
- + testsuite/tests/ghci/prog-mhu008/a/M.hs
- + testsuite/tests/ghci/prog-mhu008/all.T
- + testsuite/tests/ghci/prog-mhu008/b/M.hs
- + testsuite/tests/ghci/prog-mhu008/prog-mhu008.script
- + testsuite/tests/ghci/prog-mhu008/prog-mhu008.stdout
- + testsuite/tests/ghci/prog-mhu008/unitA
- + testsuite/tests/ghci/prog-mhu008/unitB
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- + testsuite/tests/primops/should_run/T27299.hs
- + testsuite/tests/primops/should_run/T27299.stdout
- testsuite/tests/primops/should_run/all.T
- testsuite/tests/typecheck/should_compile/T25180.stderr
- utils/haddock/html-test/ref/Bug923.html
- utils/haddock/html-test/ref/Instances.html
Changes:
=====================================
changelog.d/26610
=====================================
@@ -0,0 +1,7 @@
+section: compiler
+synopsis: Fix instance resolution for shadowed modules
+description:
+ Instances imported from modules with the same module name as the importing module
+ were dropped accidentally since we didn't account for the unit id of the imported module.
+mrs: !16648
+issues: #26610
=====================================
changelog.d/clc-442
=====================================
@@ -0,0 +1,9 @@
+section: base
+issues: #27849
+mrs: !16718
+synopsis:
+ Expose `data Unit` and `data TupleN` from `Data.Tuple` in `base`
+description:
+ The data types `data Unit` and `data TupleN` (for N from 2 to 64) are now exported from
+ `Data.Tuple` in the `base` library instead of `Data.Tuple.Experimental` in `ghc-experimental`.
+ See `CLC proposal 442 <https://github.com/haskell/core-libraries-committee/issues/442>`_.
=====================================
compiler/GHC/Driver/Env.hs
=====================================
@@ -263,13 +263,13 @@ hugCompleteSigsBelow hsc uid mn = foldr (++) [] <$>
-- | Find instances visible from the given set of imports
hugInstancesBelow :: HscEnv -> UnitId -> ModuleNameWithIsBoot -> IO (InstEnv, [FamInst])
hugInstancesBelow hsc_env uid mnwib = do
- let mn = gwib_mod mnwib
+ let mn = mkModule uid (gwib_mod mnwib)
(insts, famInsts) <-
unzip . concat <$>
hugSomeThingsBelowUs (\mod_info ->
let details = hm_details mod_info
-- Don't include instances for the current module
- in if moduleName (mi_module (hm_iface mod_info)) == mn
+ in if fmap toUnitId (mi_module (hm_iface mod_info)) == mn
then []
else [(md_insts details, md_fam_insts details)])
True -- Include -hi-boot
=====================================
libraries/base/changelog.md
=====================================
@@ -7,6 +7,7 @@
* Add `Data.List.NonEmpty.{zip{3..7},zipWith{3..7},unzip{3..7}}` ([CLC proposal #409)(https://github.com/haskell/core-libraries-committee/issues/409))
* Ensure that `Data.List.elem` and `notElem` can be specialized even when no list fusion happens. ([CLC proposal #412)(https://github.com/haskell/core-libraries-committee/issues/412))
* Introduce `Data.Double` and `Data.Float` modules. ([CLC proposal #378](https://github.com/haskell/core-libraries-committee/issues/378))
+ * Expose `data Unit` and `data TupleN` (for `N` from 2 to 64) from module `Data.Tuple` ([CLC proposal #442](https://github.com/haskell/core-libraries-committee/issues/442))
* Change `Generically a`'s `Monoid` definition to require a `Semigroup` constraint, and define its `mconcat` using `(<>)` from that constraint. ([CLC proposal #413](https://github.com/haskell/core-libraries-committee/issues/413))
* Add `withEmptyCallStack` to `GHC.Stack`. ([CLC proposal #428](https://github.com/haskell/core-libraries-committee/issues/428))
* Add new `Data.RealFloat` module re-exporting `RealFloat` from `GHC.Float` ([CLC proposal #394](https://github.com/haskell/core-libraries-committee/issues/394))
=====================================
libraries/base/src/Data/Tuple.hs
=====================================
@@ -14,13 +14,78 @@
--
module Data.Tuple
- (Solo(..),
+ (Unit(..),
+ Solo(..),
getSolo,
fst,
snd,
curry,
uncurry,
- swap
+ swap,
+ Tuple2(..),
+ Tuple3(..),
+ Tuple4(..),
+ Tuple5(..),
+ Tuple6(..),
+ Tuple7(..),
+ Tuple8(..),
+ Tuple9(..),
+ Tuple10(..),
+ Tuple11(..),
+ Tuple12(..),
+ Tuple13(..),
+ Tuple14(..),
+ Tuple15(..),
+ Tuple16(..),
+ Tuple17(..),
+ Tuple18(..),
+ Tuple19(..),
+ Tuple20(..),
+ Tuple21(..),
+ Tuple22(..),
+ Tuple23(..),
+ Tuple24(..),
+ Tuple25(..),
+ Tuple26(..),
+ Tuple27(..),
+ Tuple28(..),
+ Tuple29(..),
+ Tuple30(..),
+ Tuple31(..),
+ Tuple32(..),
+ Tuple33(..),
+ Tuple34(..),
+ Tuple35(..),
+ Tuple36(..),
+ Tuple37(..),
+ Tuple38(..),
+ Tuple39(..),
+ Tuple40(..),
+ Tuple41(..),
+ Tuple42(..),
+ Tuple43(..),
+ Tuple44(..),
+ Tuple45(..),
+ Tuple46(..),
+ Tuple47(..),
+ Tuple48(..),
+ Tuple49(..),
+ Tuple50(..),
+ Tuple51(..),
+ Tuple52(..),
+ Tuple53(..),
+ Tuple54(..),
+ Tuple55(..),
+ Tuple56(..),
+ Tuple57(..),
+ Tuple58(..),
+ Tuple59(..),
+ Tuple60(..),
+ Tuple61(..),
+ Tuple62(..),
+ Tuple63(..),
+ Tuple64(..),
) where
-import GHC.Internal.Data.Tuple
\ No newline at end of file
+import GHC.Internal.Data.Tuple
+import GHC.Tuple
\ No newline at end of file
=====================================
rts/include/stg/Prim.h
=====================================
@@ -59,16 +59,16 @@ StgWord hs_xchg32(StgWord x, StgWord val);
StgWord64 hs_xchg64(StgWord x, StgWord64 val);
/* rts/prim/bswap.c */
-StgWord16 hs_bswap16(StgWord16 x);
-StgWord32 hs_bswap32(StgWord32 x);
+StgWord hs_bswap16(StgWord x);
+StgWord hs_bswap32(StgWord x);
StgWord64 hs_bswap64(StgWord64 x);
/* rts/prim/bitrev.c
This was done as part of issue #16164.
See Note [Bit reversal primop] for more details about the implementation.*/
StgWord hs_bitrev8(StgWord x);
-StgWord16 hs_bitrev16(StgWord16 x);
-StgWord32 hs_bitrev32(StgWord32 x);
+StgWord hs_bitrev16(StgWord x);
+StgWord hs_bitrev32(StgWord x);
StgWord64 hs_bitrev64(StgWord64 x);
/* rts/prim/longlong.c */
=====================================
rts/prim/bitrev.c
=====================================
@@ -36,8 +36,8 @@ hs_bitrev8(StgWord x)
return x;
}
-StgWord16
-hs_bitrev16(StgWord16 x)
+StgWord
+hs_bitrev16(StgWord x)
{
x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1 );
x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2 );
@@ -46,14 +46,14 @@ hs_bitrev16(StgWord16 x)
return x;
}
-StgWord32
-hs_bitrev32(StgWord32 x)
+StgWord
+hs_bitrev32(StgWord x)
{
- x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1 );
- x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2 );
- x = ((x >> 4) & 0x0F0F0F0F) | ((x & 0x0F0F0F0F) << 4 );
- x = ((x >> 8) & 0x00FF00FF) | ((x & 0x00FF00FF) << 8 );
- x = ( x >> 16 ) | ( x << 16 );
+ x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1 );
+ x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2 );
+ x = ((x >> 4) & 0x0F0F0F0F) | ((x & 0x0F0F0F0F) << 4 );
+ x = ((x >> 8) & 0x00FF00FF) | ((x & 0x00FF00FF) << 8 );
+ x = ((x >> 16) & 0x0000FFFF) | ((x & 0x0000FFFF) << 16);
return x;
}
=====================================
rts/prim/bswap.c
=====================================
@@ -1,16 +1,18 @@
#include "Rts.h"
-StgWord16
-hs_bswap16(StgWord16 x)
+StgWord
+hs_bswap16(StgWord x)
{
- return ((x >> 8) | (x << 8));
+ x = (StgWord16)x;
+ return (StgWord16)((x >> 8) | (x << 8));
}
-StgWord32
-hs_bswap32(StgWord32 x)
+StgWord
+hs_bswap32(StgWord x)
{
- return ((x >> 24) | ((x >> 8) & 0xff00) |
- (x << 24) | ((x & 0xff00) << 8));
+ x = (StgWord32)x;
+ return (StgWord32)((x >> 24) | ((x >> 8) & 0xff00) |
+ (x << 24) | ((x & 0xff00) << 8));
}
StgWord64
=====================================
testsuite/tests/ghci/prog-mhu008/Makefile
=====================================
@@ -0,0 +1,3 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
=====================================
testsuite/tests/ghci/prog-mhu008/a/M.hs
=====================================
@@ -0,0 +1,4 @@
+module M (T (..)) where
+
+newtype T = MkT Int
+ deriving (Eq, Ord)
=====================================
testsuite/tests/ghci/prog-mhu008/all.T
=====================================
@@ -0,0 +1,5 @@
+test('prog-mhu008',
+ [extra_files(['a/', 'b/', 'unitA', 'unitB']),
+ cmd_prefix('ghciWayFlags=' + config.ghci_way_flags),
+ req_interp],
+ ghci_multiunit_script, [['unitA', 'unitB'], 'prog-mhu008.script'])
=====================================
testsuite/tests/ghci/prog-mhu008/b/M.hs
=====================================
@@ -0,0 +1,11 @@
+{-# LANGUAGE PackageImports #-}
+
+module M
+ ( module Export
+ , cmp
+ ) where
+
+import "a" M as Export
+
+cmp :: T -> T -> Bool
+cmp x y = x <= y
=====================================
testsuite/tests/ghci/prog-mhu008/prog-mhu008.script
=====================================
@@ -0,0 +1,5 @@
+:set -XPackageImports
+import "a" M qualified as MA
+import "b" M qualified as MB
+
+MB.cmp (MA.MkT 1) (MA.MkT 2)
=====================================
testsuite/tests/ghci/prog-mhu008/prog-mhu008.stdout
=====================================
@@ -0,0 +1 @@
+True
=====================================
testsuite/tests/ghci/prog-mhu008/unitA
=====================================
@@ -0,0 +1,5 @@
+-this-unit-id a-0-inplace
+-this-package-name a
+-i
+-ia
+M
=====================================
testsuite/tests/ghci/prog-mhu008/unitB
=====================================
@@ -0,0 +1,6 @@
+-this-unit-id b-0-inplace
+-this-package-name b
+-package-id a-0-inplace
+-i
+-ib
+M
=====================================
testsuite/tests/interface-stability/base-exports.stdout
=====================================
@@ -1760,6 +1760,134 @@ module Data.Tuple where
pattern Solo :: forall a. a -> Solo a
type Solo :: * -> *
data Solo a = MkSolo a
+ type Tuple10 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple10 a b c d e f g h i j = (,,,,,,,,,) a b c d e f g h i j
+ type Tuple11 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple11 a b c d e f g h i j k = (,,,,,,,,,,) a b c d e f g h i j k
+ type Tuple12 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple12 a b c d e f g h i j k l = (,,,,,,,,,,,) a b c d e f g h i j k l
+ type Tuple13 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple13 a b c d e f g h i j k l m = (,,,,,,,,,,,,) a b c d e f g h i j k l m
+ type Tuple14 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple14 a b c d e f g h i j k l m n = (,,,,,,,,,,,,,) a b c d e f g h i j k l m n
+ type Tuple15 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple15 a b c d e f g h i j k l m n o = (,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o
+ type Tuple16 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple16 a b c d e f g h i j k l m n o p = (,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p
+ type Tuple17 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple17 a b c d e f g h i j k l m n o p q = (,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q
+ type Tuple18 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple18 a b c d e f g h i j k l m n o p q r = (,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r
+ type Tuple19 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple19 a b c d e f g h i j k l m n o p q r s = (,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s
+ type Tuple2 :: * -> * -> *
+ data Tuple2 a b = (,) a b
+ type Tuple20 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple20 a b c d e f g h i j k l m n o p q r s t = (,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t
+ type Tuple21 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple21 a b c d e f g h i j k l m n o p q r s t u = (,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u
+ type Tuple22 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple22 a b c d e f g h i j k l m n o p q r s t u v = (,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v
+ type Tuple23 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple23 a b c d e f g h i j k l m n o p q r s t u v w = (,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w
+ type Tuple24 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple24 a b c d e f g h i j k l m n o p q r s t u v w x = (,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x
+ type Tuple25 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple25 a b c d e f g h i j k l m n o p q r s t u v w x y = (,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y
+ type Tuple26 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple26 a b c d e f g h i j k l m n o p q r s t u v w x y z = (,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z
+ type Tuple27 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple27 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 = (,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26
+ type Tuple28 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple28 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27
+ type Tuple29 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple29 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28
+ type Tuple3 :: * -> * -> * -> *
+ data Tuple3 a b c = (,,) a b c
+ type Tuple30 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple30 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29
+ type Tuple31 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple31 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30
+ type Tuple32 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple32 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31
+ type Tuple33 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple33 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32
+ type Tuple34 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple34 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33
+ type Tuple35 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple35 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34
+ type Tuple36 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple36 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35
+ type Tuple37 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple37 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36
+ type Tuple38 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple38 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37
+ type Tuple39 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple39 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38
+ type Tuple4 :: * -> * -> * -> * -> *
+ data Tuple4 a b c d = (,,,) a b c d
+ type Tuple40 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple40 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39
+ type Tuple41 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple41 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40
+ type Tuple42 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple42 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41
+ type Tuple43 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple43 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42
+ type Tuple44 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple44 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43
+ type Tuple45 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple45 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44
+ type Tuple46 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple46 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45
+ type Tuple47 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple47 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46
+ type Tuple48 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple48 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47
+ type Tuple49 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple49 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48
+ type Tuple5 :: * -> * -> * -> * -> * -> *
+ data Tuple5 a b c d e = (,,,,) a b c d e
+ type Tuple50 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple50 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49
+ type Tuple51 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple51 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50
+ type Tuple52 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple52 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51
+ type Tuple53 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple53 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52
+ type Tuple54 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple54 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53
+ type Tuple55 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple55 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54
+ type Tuple56 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple56 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55
+ type Tuple57 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple57 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56
+ type Tuple58 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple58 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57
+ type Tuple59 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple59 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58
+ type Tuple6 :: * -> * -> * -> * -> * -> * -> *
+ data Tuple6 a b c d e f = (,,,,,) a b c d e f
+ type Tuple60 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple60 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59
+ type Tuple61 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple61 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60
+ type Tuple62 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple62 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61
+ type Tuple63 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple63 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62
+ type Tuple64 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple64 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 t63 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 t63
+ type Tuple7 :: * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple7 a b c d e f g = (,,,,,,) a b c d e f g
+ type Tuple8 :: * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple8 a b c d e f g h = (,,,,,,,) a b c d e f g h
+ type Tuple9 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple9 a b c d e f g h i = (,,,,,,,,) a b c d e f g h i
+ type Unit :: *
+ data Unit = ()
curry :: forall a b c. ((a, b) -> c) -> a -> b -> c
fst :: forall a b. (a, b) -> a
getSolo :: forall a. Solo a -> a
=====================================
testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
=====================================
@@ -1760,6 +1760,134 @@ module Data.Tuple where
pattern Solo :: forall a. a -> Solo a
type Solo :: * -> *
data Solo a = MkSolo a
+ type Tuple10 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple10 a b c d e f g h i j = (,,,,,,,,,) a b c d e f g h i j
+ type Tuple11 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple11 a b c d e f g h i j k = (,,,,,,,,,,) a b c d e f g h i j k
+ type Tuple12 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple12 a b c d e f g h i j k l = (,,,,,,,,,,,) a b c d e f g h i j k l
+ type Tuple13 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple13 a b c d e f g h i j k l m = (,,,,,,,,,,,,) a b c d e f g h i j k l m
+ type Tuple14 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple14 a b c d e f g h i j k l m n = (,,,,,,,,,,,,,) a b c d e f g h i j k l m n
+ type Tuple15 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple15 a b c d e f g h i j k l m n o = (,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o
+ type Tuple16 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple16 a b c d e f g h i j k l m n o p = (,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p
+ type Tuple17 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple17 a b c d e f g h i j k l m n o p q = (,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q
+ type Tuple18 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple18 a b c d e f g h i j k l m n o p q r = (,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r
+ type Tuple19 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple19 a b c d e f g h i j k l m n o p q r s = (,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s
+ type Tuple2 :: * -> * -> *
+ data Tuple2 a b = (,) a b
+ type Tuple20 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple20 a b c d e f g h i j k l m n o p q r s t = (,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t
+ type Tuple21 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple21 a b c d e f g h i j k l m n o p q r s t u = (,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u
+ type Tuple22 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple22 a b c d e f g h i j k l m n o p q r s t u v = (,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v
+ type Tuple23 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple23 a b c d e f g h i j k l m n o p q r s t u v w = (,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w
+ type Tuple24 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple24 a b c d e f g h i j k l m n o p q r s t u v w x = (,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x
+ type Tuple25 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple25 a b c d e f g h i j k l m n o p q r s t u v w x y = (,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y
+ type Tuple26 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple26 a b c d e f g h i j k l m n o p q r s t u v w x y z = (,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z
+ type Tuple27 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple27 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 = (,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26
+ type Tuple28 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple28 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27
+ type Tuple29 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple29 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28
+ type Tuple3 :: * -> * -> * -> *
+ data Tuple3 a b c = (,,) a b c
+ type Tuple30 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple30 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29
+ type Tuple31 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple31 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30
+ type Tuple32 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple32 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31
+ type Tuple33 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple33 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32
+ type Tuple34 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple34 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33
+ type Tuple35 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple35 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34
+ type Tuple36 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple36 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35
+ type Tuple37 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple37 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36
+ type Tuple38 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple38 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37
+ type Tuple39 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple39 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38
+ type Tuple4 :: * -> * -> * -> * -> *
+ data Tuple4 a b c d = (,,,) a b c d
+ type Tuple40 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple40 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39
+ type Tuple41 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple41 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40
+ type Tuple42 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple42 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41
+ type Tuple43 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple43 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42
+ type Tuple44 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple44 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43
+ type Tuple45 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple45 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44
+ type Tuple46 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple46 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45
+ type Tuple47 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple47 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46
+ type Tuple48 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple48 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47
+ type Tuple49 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple49 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48
+ type Tuple5 :: * -> * -> * -> * -> * -> *
+ data Tuple5 a b c d e = (,,,,) a b c d e
+ type Tuple50 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple50 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49
+ type Tuple51 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple51 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50
+ type Tuple52 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple52 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51
+ type Tuple53 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple53 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52
+ type Tuple54 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple54 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53
+ type Tuple55 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple55 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54
+ type Tuple56 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple56 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55
+ type Tuple57 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple57 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56
+ type Tuple58 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple58 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57
+ type Tuple59 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple59 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58
+ type Tuple6 :: * -> * -> * -> * -> * -> * -> *
+ data Tuple6 a b c d e f = (,,,,,) a b c d e f
+ type Tuple60 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple60 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59
+ type Tuple61 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple61 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60
+ type Tuple62 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple62 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61
+ type Tuple63 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple63 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62
+ type Tuple64 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple64 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 t63 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 t63
+ type Tuple7 :: * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple7 a b c d e f g = (,,,,,,) a b c d e f g
+ type Tuple8 :: * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple8 a b c d e f g h = (,,,,,,,) a b c d e f g h
+ type Tuple9 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple9 a b c d e f g h i = (,,,,,,,,) a b c d e f g h i
+ type Unit :: *
+ data Unit = ()
curry :: forall a b c. ((a, b) -> c) -> a -> b -> c
fst :: forall a b. (a, b) -> a
getSolo :: forall a. Solo a -> a
=====================================
testsuite/tests/interface-stability/base-exports.stdout-mingw32
=====================================
@@ -1760,6 +1760,134 @@ module Data.Tuple where
pattern Solo :: forall a. a -> Solo a
type Solo :: * -> *
data Solo a = MkSolo a
+ type Tuple10 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple10 a b c d e f g h i j = (,,,,,,,,,) a b c d e f g h i j
+ type Tuple11 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple11 a b c d e f g h i j k = (,,,,,,,,,,) a b c d e f g h i j k
+ type Tuple12 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple12 a b c d e f g h i j k l = (,,,,,,,,,,,) a b c d e f g h i j k l
+ type Tuple13 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple13 a b c d e f g h i j k l m = (,,,,,,,,,,,,) a b c d e f g h i j k l m
+ type Tuple14 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple14 a b c d e f g h i j k l m n = (,,,,,,,,,,,,,) a b c d e f g h i j k l m n
+ type Tuple15 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple15 a b c d e f g h i j k l m n o = (,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o
+ type Tuple16 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple16 a b c d e f g h i j k l m n o p = (,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p
+ type Tuple17 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple17 a b c d e f g h i j k l m n o p q = (,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q
+ type Tuple18 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple18 a b c d e f g h i j k l m n o p q r = (,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r
+ type Tuple19 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple19 a b c d e f g h i j k l m n o p q r s = (,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s
+ type Tuple2 :: * -> * -> *
+ data Tuple2 a b = (,) a b
+ type Tuple20 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple20 a b c d e f g h i j k l m n o p q r s t = (,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t
+ type Tuple21 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple21 a b c d e f g h i j k l m n o p q r s t u = (,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u
+ type Tuple22 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple22 a b c d e f g h i j k l m n o p q r s t u v = (,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v
+ type Tuple23 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple23 a b c d e f g h i j k l m n o p q r s t u v w = (,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w
+ type Tuple24 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple24 a b c d e f g h i j k l m n o p q r s t u v w x = (,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x
+ type Tuple25 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple25 a b c d e f g h i j k l m n o p q r s t u v w x y = (,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y
+ type Tuple26 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple26 a b c d e f g h i j k l m n o p q r s t u v w x y z = (,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z
+ type Tuple27 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple27 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 = (,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26
+ type Tuple28 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple28 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27
+ type Tuple29 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple29 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28
+ type Tuple3 :: * -> * -> * -> *
+ data Tuple3 a b c = (,,) a b c
+ type Tuple30 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple30 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29
+ type Tuple31 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple31 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30
+ type Tuple32 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple32 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31
+ type Tuple33 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple33 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32
+ type Tuple34 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple34 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33
+ type Tuple35 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple35 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34
+ type Tuple36 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple36 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35
+ type Tuple37 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple37 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36
+ type Tuple38 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple38 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37
+ type Tuple39 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple39 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38
+ type Tuple4 :: * -> * -> * -> * -> *
+ data Tuple4 a b c d = (,,,) a b c d
+ type Tuple40 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple40 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39
+ type Tuple41 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple41 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40
+ type Tuple42 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple42 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41
+ type Tuple43 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple43 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42
+ type Tuple44 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple44 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43
+ type Tuple45 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple45 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44
+ type Tuple46 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple46 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45
+ type Tuple47 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple47 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46
+ type Tuple48 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple48 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47
+ type Tuple49 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple49 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48
+ type Tuple5 :: * -> * -> * -> * -> * -> *
+ data Tuple5 a b c d e = (,,,,) a b c d e
+ type Tuple50 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple50 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49
+ type Tuple51 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple51 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50
+ type Tuple52 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple52 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51
+ type Tuple53 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple53 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52
+ type Tuple54 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple54 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53
+ type Tuple55 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple55 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54
+ type Tuple56 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple56 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55
+ type Tuple57 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple57 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56
+ type Tuple58 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple58 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57
+ type Tuple59 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple59 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58
+ type Tuple6 :: * -> * -> * -> * -> * -> * -> *
+ data Tuple6 a b c d e f = (,,,,,) a b c d e f
+ type Tuple60 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple60 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59
+ type Tuple61 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple61 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60
+ type Tuple62 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple62 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61
+ type Tuple63 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple63 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62
+ type Tuple64 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple64 a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 t63 = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 t42 t43 t44 t45 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 t56 t57 t58 t59 t60 t61 t62 t63
+ type Tuple7 :: * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple7 a b c d e f g = (,,,,,,) a b c d e f g
+ type Tuple8 :: * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple8 a b c d e f g h = (,,,,,,,) a b c d e f g h
+ type Tuple9 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> *
+ data Tuple9 a b c d e f g h i = (,,,,,,,,) a b c d e f g h i
+ type Unit :: *
+ data Unit = ()
curry :: forall a b c. ((a, b) -> c) -> a -> b -> c
fst :: forall a b. (a, b) -> a
getSolo :: forall a. Solo a -> a
=====================================
testsuite/tests/primops/should_run/T27299.hs
=====================================
@@ -0,0 +1,23 @@
+{-# LANGUAGE MagicHash #-}
+import GHC.Exts
+import GHC.Word
+import Numeric
+
+main :: IO ()
+main = do
+ putStrLn $ showHex (W# (bitReverse8# 0x55##)) ""
+ putStrLn $ showHex (W# (bitReverse8# 0xAA##)) ""
+ putStrLn $ showHex (W# (bitReverse16# 0x5555##)) ""
+ putStrLn $ showHex (W# (bitReverse16# 0xAAAA##)) ""
+ putStrLn $ showHex (W# (bitReverse32# 0x5555_5555##)) ""
+ putStrLn $ showHex (W# (bitReverse32# 0xAAAA_AAAA##)) ""
+ putStrLn $ showHex (W# (byteSwap16# 0xABCD##)) ""
+ putStrLn $ showHex (W# (byteSwap32# 0xABCD_EF12##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse8# 0x55##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse8# 0xAA##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse16# 0x5555##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse16# 0xAAAA##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse32# 0x5555_5555##)) ""
+ putStrLn $ showHex (W# (noinline bitReverse32# 0xAAAA_AAAA##)) ""
+ putStrLn $ showHex (W# (noinline byteSwap16# 0xABCD##)) ""
+ putStrLn $ showHex (W# (noinline byteSwap32# 0xABCD_EF12##)) ""
=====================================
testsuite/tests/primops/should_run/T27299.stdout
=====================================
@@ -0,0 +1,16 @@
+aa
+55
+aaaa
+5555
+aaaaaaaa
+55555555
+cdab
+12efcdab
+aa
+55
+aaaa
+5555
+aaaaaaaa
+55555555
+cdab
+12efcdab
=====================================
testsuite/tests/primops/should_run/all.T
=====================================
@@ -91,3 +91,4 @@ test('T24496'
]
, compile_and_run, ['-O'])
test('T6026', normal, compile_and_run, [''])
+test('T27299', normal, compile_and_run, [''])
=====================================
testsuite/tests/typecheck/should_compile/T25180.stderr
=====================================
@@ -5,6 +5,9 @@ T25180.hs:12:8: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
Valid hole fits include
tup0 :: () (bound at T25180.hs:12:1)
() :: () (bound at <wired into compiler>)
+ () :: ()
+ (imported from ‘Data.Tuple’ at T25180.hs:6:1-17
+ (and originally defined in ‘GHC.Internal.Tuple’))
mempty :: forall a. Monoid a => a
with mempty @()
(imported from ‘Prelude’
@@ -60,6 +63,10 @@ T25180.hs:26:8: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
(,) :: forall a b. a -> b -> (a, b)
with (,) @a @b
(bound at <wired into compiler>)
+ (,) :: forall a b. a -> b -> (a, b)
+ with (,) @a @b
+ (imported from ‘Data.Tuple’ at T25180.hs:6:1-17
+ (and originally defined in ‘GHC.Internal.Tuple’))
T25180.hs:33:8: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
• Found hole: _ :: a -> b -> c -> (a, b, c)
@@ -75,6 +82,10 @@ T25180.hs:33:8: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
(,,) :: forall a b c. a -> b -> c -> (a, b, c)
with (,,) @a @b @c
(bound at <wired into compiler>)
+ (,,) :: forall a b c. a -> b -> c -> (a, b, c)
+ with (,,) @a @b @c
+ (imported from ‘Data.Tuple’ at T25180.hs:6:1-17
+ (and originally defined in ‘GHC.Internal.Tuple’))
T25180.hs:38:11: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
• Found hole: _ :: (# #)
=====================================
utils/haddock/html-test/ref/Bug923.html
=====================================
@@ -76,7 +76,9 @@
>forall</span
> a. a -> <a href="#" title="Bug923"
>T</a
- > ('(,) a :: <a href="#" title="Data.Kind"
+ > ('<a href="#" title="Data.Tuple"
+ >(,)</a
+ > a :: <a href="#" title="Data.Kind"
>Type</a
> -> (<a href="#" title="Data.Kind"
>Type</a
@@ -126,7 +128,9 @@
>forall</span
> a. a -> <a href="#" title="Bug923"
>T</a
- > ('(,) a :: <a href="#" title="Data.Kind"
+ > ('<a href="#" title="Data.Tuple"
+ >(,)</a
+ > a :: <a href="#" title="Data.Kind"
>Type</a
> -> (<a href="#" title="Data.Kind"
>Type</a
@@ -156,7 +160,9 @@
>Eq</a
> (<a href="#" title="Bug923"
>T</a
- > ('(,) a :: <a href="#" title="Data.Kind"
+ > ('<a href="#" title="Data.Tuple"
+ >(,)</a
+ > a :: <a href="#" title="Data.Kind"
>Type</a
> -> (<a href="#" title="Data.Kind"
>Type</a
@@ -188,7 +194,9 @@
>(==)</a
> :: <a href="#" title="Bug923"
>T</a
- > ('(,) a :: <a href="#" title="Data.Kind"
+ > ('<a href="#" title="Data.Tuple"
+ >(,)</a
+ > a :: <a href="#" title="Data.Kind"
>Type</a
> -> (<a href="#" title="Data.Kind"
>Type</a
@@ -196,7 +204,9 @@
>Type</a
>)) -> <a href="#" title="Bug923"
>T</a
- > ('(,) a :: <a href="#" title="Data.Kind"
+ > ('<a href="#" title="Data.Tuple"
+ >(,)</a
+ > a :: <a href="#" title="Data.Kind"
>Type</a
> -> (<a href="#" title="Data.Kind"
>Type</a
@@ -212,7 +222,9 @@
>(/=)</a
> :: <a href="#" title="Bug923"
>T</a
- > ('(,) a :: <a href="#" title="Data.Kind"
+ > ('<a href="#" title="Data.Tuple"
+ >(,)</a
+ > a :: <a href="#" title="Data.Kind"
>Type</a
> -> (<a href="#" title="Data.Kind"
>Type</a
@@ -220,7 +232,9 @@
>Type</a
>)) -> <a href="#" title="Bug923"
>T</a
- > ('(,) a :: <a href="#" title="Data.Kind"
+ > ('<a href="#" title="Data.Tuple"
+ >(,)</a
+ > a :: <a href="#" title="Data.Kind"
>Type</a
> -> (<a href="#" title="Data.Kind"
>Type</a
=====================================
utils/haddock/html-test/ref/Instances.html
=====================================
@@ -450,7 +450,9 @@
>)</span
> => <a href="#" title="Instances"
>Foo</a
- > ((,) (f a))</span
+ > (<a href="#" title="Data.Tuple"
+ >(,)</a
+ > (f a))</span
> <a href="#" class="selflink"
>#</a
></td
@@ -560,7 +562,9 @@
></span
> <a href="#" title="Instances"
>Foo</a
- > ((,,) a a)</span
+ > (<a href="#" title="Data.Tuple"
+ >(,,)</a
+ > a a)</span
> <a href="#" class="selflink"
>#</a
></td
@@ -1164,9 +1168,13 @@
></span
> <a href="#" title="Instances"
>Foo</a
- > ((,,) a b) => <a href="#" title="Instances"
+ > (<a href="#" title="Data.Tuple"
+ >(,,)</a
+ > a b) => <a href="#" title="Instances"
>Bar</a
- > ((,,) a b) (a, b, a)</span
+ > (<a href="#" title="Data.Tuple"
+ >(,,)</a
+ > a b) (a, b, a)</span
> <a href="#" class="selflink"
>#</a
></td
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e155f2576ea957c3ee5ef4478b802d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e155f2576ea957c3ee5ef4478b802d…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0