summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2021-04-23 15:52:49 -0400
committerBen Gamari <ben@smart-cactus.org>2021-09-23 19:33:02 -0400
commite88e53b4e40b693a9f1c50c649966cd64879a30b (patch)
tree7b3c452a103876433ed35b9f154c3344b10100bb
parentcd79e2164d3b2d1ad94aab5a95038f4c36d8c57e (diff)
downloadhaskell-wip/T19703-ghc-8.8.tar.gz
compiler: Introduce and use RoughMap for instance environmentswip/T19703-ghc-8.8
-rw-r--r--compiler/basicTypes/NameEnv.hs22
-rw-r--r--compiler/coreSyn/CoreLint.hs4
-rw-r--r--compiler/coreSyn/RoughMap.hs248
-rw-r--r--compiler/ghc.cabal.in1
-rw-r--r--compiler/iface/MkIface.hs11
-rw-r--r--compiler/iface/TcIface.hs8
-rw-r--r--compiler/main/GHC.hs7
-rw-r--r--compiler/main/HscTypes.hs20
-rw-r--r--compiler/main/TidyPgm.hs8
-rw-r--r--compiler/typecheck/FunDeps.hs8
-rw-r--r--compiler/typecheck/TcBackpack.hs6
-rw-r--r--compiler/typecheck/TcRnDriver.hs12
-rw-r--r--compiler/types/FamInstEnv.hs113
-rw-r--r--compiler/types/InstEnv.hs137
-rw-r--r--compiler/types/Unify.hs61
-rw-r--r--compiler/utils/Bag.hs10
-rw-r--r--compiler/utils/UniqDFM.hs4
-rw-r--r--compiler/utils/UniqFM.hs15
-rw-r--r--testsuite/tests/ghci/scripts/T12550.stdout42
-rw-r--r--testsuite/tests/ghci/scripts/T4175.stdout42
-rw-r--r--testsuite/tests/ghci/scripts/T7627.stdout24
-rw-r--r--testsuite/tests/ghci/scripts/T8469.stdout10
-rw-r--r--testsuite/tests/ghci/scripts/T8535.stdout4
-rw-r--r--testsuite/tests/ghci/scripts/T8674.stdout2
-rw-r--r--testsuite/tests/ghci/scripts/T9881.stdout16
-rw-r--r--testsuite/tests/ghci/scripts/ghci008.stdout2
-rw-r--r--testsuite/tests/ghci/scripts/ghci011.stdout40
-rw-r--r--testsuite/tests/ghci/scripts/ghci020.stdout4
-rw-r--r--testsuite/tests/ghci/scripts/ghci064.stdout49
-rw-r--r--testsuite/tests/ghci/should_run/T10145.stdout4
-rw-r--r--testsuite/tests/ghci/should_run/T18594.stdout15
-rw-r--r--testsuite/tests/perf/compiler/T19703/Makefile4
-rw-r--r--testsuite/tests/perf/compiler/T19703/genT19703.py13
-rw-r--r--testsuite/tests/showIface/Orphans.stdout4
-rw-r--r--testsuite/tests/th/T17296.stderr14
-rw-r--r--testsuite/tests/th/T1835.stdout6
-rw-r--r--testsuite/tests/th/T8953.stderr12
-rw-r--r--testsuite/tests/th/TH_reifyDecl1.stderr8
m---------utils/haddock0
m---------utils/hsc2hs0
40 files changed, 674 insertions, 336 deletions
diff --git a/compiler/basicTypes/NameEnv.hs b/compiler/basicTypes/NameEnv.hs
index 632ea7742e..ea70dd4715 100644
--- a/compiler/basicTypes/NameEnv.hs
+++ b/compiler/basicTypes/NameEnv.hs
@@ -24,9 +24,13 @@ module NameEnv (
DNameEnv,
emptyDNameEnv,
+ isEmptyDNameEnv,
lookupDNameEnv,
- mapDNameEnv,
+ mapDNameEnv, eltsDNameEnv,
alterDNameEnv,
+ plusDNameEnv_C,
+ foldDNameEnv,
+ nonDetStrictFoldDNameEnv,
-- ** Dependency analysis
depAnal
) where
@@ -144,11 +148,27 @@ type DNameEnv a = UniqDFM a
emptyDNameEnv :: DNameEnv a
emptyDNameEnv = emptyUDFM
+isEmptyDNameEnv :: DNameEnv a -> Bool
+isEmptyDNameEnv = isNullUDFM
+
lookupDNameEnv :: DNameEnv a -> Name -> Maybe a
lookupDNameEnv = lookupUDFM
mapDNameEnv :: (a -> b) -> DNameEnv a -> DNameEnv b
mapDNameEnv = mapUDFM
+eltsDNameEnv :: DNameEnv a -> [a]
+eltsDNameEnv = eltsUDFM
+
alterDNameEnv :: (Maybe a -> Maybe a) -> DNameEnv a -> Name -> DNameEnv a
alterDNameEnv = alterUDFM
+
+foldDNameEnv :: (a -> b -> b) -> b -> DNameEnv a -> b
+foldDNameEnv = foldUDFM
+
+plusDNameEnv_C :: (elt -> elt -> elt) -> DNameEnv elt -> DNameEnv elt -> DNameEnv elt
+plusDNameEnv_C = plusUDFM_C
+
+nonDetStrictFoldDNameEnv :: (a -> b -> b) -> b -> DNameEnv a -> b
+nonDetStrictFoldDNameEnv = nonDetStrictFoldUDFM
+
diff --git a/compiler/coreSyn/CoreLint.hs b/compiler/coreSyn/CoreLint.hs
index 088272aae2..be7448564a 100644
--- a/compiler/coreSyn/CoreLint.hs
+++ b/compiler/coreSyn/CoreLint.hs
@@ -57,7 +57,7 @@ import PrelNames
import Outputable
import FastString
import Util
-import InstEnv ( instanceDFunId )
+import InstEnv ( instanceDFunId, instEnvElts )
import OptCoercion ( checkAxInstCo )
import UniqSupply
import CoreArity ( typeArity )
@@ -381,7 +381,7 @@ interactiveInScope hsc_env
ictxt = hsc_IC hsc_env
(cls_insts, _fam_insts) = ic_instances ictxt
te1 = mkTypeEnvWithImplicits (ic_tythings ictxt)
- te = extendTypeEnvWithIds te1 (map instanceDFunId cls_insts)
+ te = extendTypeEnvWithIds te1 (map instanceDFunId $ instEnvElts cls_insts)
ids = typeEnvIds te
tyvars = tyCoVarsOfTypesList $ map idType ids
-- Why the type variables? How can the top level envt have free tyvars?
diff --git a/compiler/coreSyn/RoughMap.hs b/compiler/coreSyn/RoughMap.hs
new file mode 100644
index 0000000000..d9fcc88ceb
--- /dev/null
+++ b/compiler/coreSyn/RoughMap.hs
@@ -0,0 +1,248 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE BangPatterns #-}
+
+-- | 'RoughMap' is an approximate finite map data structure keyed on
+-- @['RoughMatchTc']@. This is useful when keying maps on lists of 'Type's
+-- (e.g. an instance head).
+module RoughMap
+ ( -- * RoughMatchTc
+ RoughMatchTc(..)
+ , isRoughOtherTc
+ , typeToRoughMatchTc
+
+ -- * RoughMap
+ , RoughMap
+ , emptyRM
+ , lookupRM
+ , lookupRM'
+ , insertRM
+ , filterRM
+ , filterMatchingRM
+ , elemsRM
+ , sizeRM
+ , foldRM
+ , unionRM
+ ) where
+
+#include "HsVersions.h"
+
+import GhcPrelude
+
+import Bag
+import TyCon
+import Type
+import Outputable
+import Panic
+import Name
+import NameEnv
+import Util
+
+import Control.Monad (join)
+import Data.Data (Data)
+
+{-
+Note [Rough maps of Types]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-}
+
+data RoughMatchTc
+ = KnownTc Name -- INVARIANT: Name refers to a TyCon tc that responds
+ -- true to `isGenerativeTyCon tc Nominal`. See
+ -- Note [Rough matching in class and family instances]
+ | OtherTc -- e.g. type variable at the head
+ deriving( Data )
+
+instance Outputable RoughMatchTc where
+ ppr (KnownTc nm) = text "KnownTc" <+> ppr nm
+ ppr OtherTc = text "OtherTc"
+
+isRoughOtherTc :: RoughMatchTc -> Bool
+isRoughOtherTc OtherTc = True
+isRoughOtherTc (KnownTc {}) = False
+
+typeToRoughMatchTc :: Type -> RoughMatchTc
+typeToRoughMatchTc ty
+ | Just (ty', _) <- splitCastTy_maybe ty = typeToRoughMatchTc ty'
+ | Just (tc,_) <- splitTyConApp_maybe ty
+ , not (isTypeFamilyTyCon tc) = ASSERT2(isGenerativeTyCon tc Nominal, ppr tc)
+ KnownTc $! tyConName tc
+ -- See Note [Rough matching in class and family instances]
+ | otherwise = OtherTc
+
+-- | Trie of @[RoughMatchTc]@
+--
+-- *Examples*
+-- @
+-- insert [OtherTc] 1
+-- insert [OtherTc] 2
+-- lookup [OtherTc] == [1,2]
+-- @
+data RoughMap a = RM { rm_empty :: Bag a
+ , rm_known :: !(DNameEnv (RoughMap a))
+ -- See Note [InstEnv determinism] in GHC.Core.InstEnv
+ , rm_unknown :: !(RoughMap a) }
+ | RMEmpty -- an optimised (finite) form of emptyRM
+ -- invariant: Empty RoughMaps are always represented with RMEmpty
+ deriving (Functor)
+
+emptyRM :: RoughMap a
+emptyRM = RMEmpty
+
+-- | Order of result is deterministic.
+lookupRM :: [RoughMatchTc] -> RoughMap a -> [a]
+lookupRM tcs rm = bagToList (lookupRM' tcs rm)
+
+-- | N.B. Returns a 'Bag', which allows us to avoid rebuilding all of the lists
+-- we find in 'rm_empty', which would otherwise be necessary due to '++' if we
+-- returned a list.
+lookupRM' :: [RoughMatchTc] -> RoughMap a -> Bag a
+lookupRM' _ RMEmpty = emptyBag
+lookupRM' [] rm = listToBag $ elemsRM rm
+lookupRM' (KnownTc tc : tcs) rm = foldl' unionBags emptyBag
+ [ maybe emptyBag (lookupRM' tcs) (lookupDNameEnv (rm_known rm) tc)
+ , lookupRM' tcs (rm_unknown rm)
+ , rm_empty rm
+ ]
+lookupRM' (OtherTc : tcs) rm = foldl' unionBags emptyBag
+ [ foldMap (lookupRM' tcs) (eltsDNameEnv $ rm_known rm)
+ , lookupRM' tcs (rm_unknown rm)
+ , rm_empty rm
+ ]
+
+unionRM :: RoughMap a -> RoughMap a -> RoughMap a
+unionRM RMEmpty a = a
+unionRM a RMEmpty = a
+unionRM a b =
+ RM { rm_empty = rm_empty a `unionBags` rm_empty b
+ , rm_known = plusDNameEnv_C unionRM (rm_known a) (rm_known b)
+ , rm_unknown = rm_unknown a `unionRM` rm_unknown b
+ }
+
+{-
+Note [RoughMap]
+~~~~~~~~~~~~~~~
+A RoughMap is semantically a list of (key,value) pairs, where
+ key :: [RoughMatchTc]
+So, writing # for `OtherTc`, and Int for `KnownTc "Int"`, we might have
+ [ ([#, Int, Maybe, #, Int], v1)
+ , ([Int, #, List], v2 ]
+
+We lookup a key of type [RoughMatchTc], and return the list of all values whose
+keys "match", where matching means:
+ * OtherTc matches anything
+ * `KnownTc n1` matches OtherTc, or `KnownTc n2` if n1=n2
+ * If the lists are of different length, extend the shorter with OtherTc
+
+Given the above map, here are the results of some lookups:
+ Lookup key Result
+ -------------------------
+ [Int, Int] [v1,v2]
+ [Int,Int,List] [v2]
+ [Bool] []
+
+The idea is that we can use a `RoughMap` as a pre-filter, to produce a
+short-list of candidates to examine more closely.
+-}
+
+ -- TODO: Including rm_empty due to Note [Eta reduction for data families]
+ -- in GHC.Core.Coercion.Axiom. e.g., we may have an environment which includes
+ -- data instance Fam Int a = ...
+ -- which will result in `axiom ax :: Fam Int ~ FamInt` and an FamInst with
+ -- `fi_tcs = [Int]`, `fi_eta_tvs = [a]`. We need to make sure that this
+ -- instance matches when we are looking for an instance `Fam Int a`.
+
+insertRM :: [RoughMatchTc] -> a -> RoughMap a -> RoughMap a
+insertRM k v RMEmpty =
+ insertRM k v $ RM { rm_empty = emptyBag
+ , rm_known = emptyDNameEnv
+ , rm_unknown = emptyRM }
+insertRM [] v rm@(RM {}) =
+ rm { rm_empty = v `consBag` rm_empty rm }
+insertRM (KnownTc k : ks) v rm@(RM {}) =
+ rm { rm_known = alterDNameEnv f (rm_known rm) k }
+ where
+ f Nothing = Just $ insertRM ks v emptyRM
+ f (Just m) = Just $ insertRM ks v m
+insertRM (OtherTc : ks) v rm@(RM {}) =
+ rm { rm_unknown = insertRM ks v (rm_unknown rm) }
+
+filterRM :: (a -> Bool) -> RoughMap a -> RoughMap a
+filterRM _ RMEmpty = RMEmpty
+filterRM pred rm =
+ normalise $ RM {
+ rm_empty = filterBag pred (rm_empty rm),
+ rm_known = mapDNameEnv (filterRM pred) (rm_known rm),
+ rm_unknown = filterRM pred (rm_unknown rm)
+ }
+
+-- | Place a 'RoughMap' in normal form, turning all empty 'RM's into
+-- 'RMEmpty's. Necessary after removing items.
+normalise :: RoughMap a -> RoughMap a
+normalise RMEmpty = RMEmpty
+normalise (RM empty known RMEmpty)
+ | isEmptyBag empty
+ , isEmptyDNameEnv known = RMEmpty
+normalise rm = rm
+
+-- | Filter all elements that might match a particular key with the given
+-- predicate.
+filterMatchingRM :: (a -> Bool) -> [RoughMatchTc] -> RoughMap a -> RoughMap a
+filterMatchingRM _ _ RMEmpty = RMEmpty
+filterMatchingRM pred [] rm = filterRM pred rm
+filterMatchingRM pred (KnownTc tc : tcs) rm =
+ normalise $ RM {
+ rm_empty = filterBag pred (rm_empty rm),
+ rm_known = alterDNameEnv (join . fmap (dropEmpty . filterMatchingRM pred tcs)) (rm_known rm) tc,
+ rm_unknown = filterMatchingRM pred tcs (rm_unknown rm)
+ }
+filterMatchingRM pred (OtherTc : tcs) rm =
+ normalise $ RM {
+ rm_empty = filterBag pred (rm_empty rm),
+ rm_known = mapDNameEnv (filterMatchingRM pred tcs) (rm_known rm),
+ rm_unknown = filterMatchingRM pred tcs (rm_unknown rm)
+ }
+
+dropEmpty :: RoughMap a -> Maybe (RoughMap a)
+dropEmpty RMEmpty = Nothing
+dropEmpty rm = Just rm
+
+elemsRM :: RoughMap a -> [a]
+elemsRM = foldRM (:) []
+
+foldRM :: (a -> b -> b) -> b -> RoughMap a -> b
+foldRM f = go
+ where
+ -- N.B. local worker ensures that the loop can be specialised to the fold
+ -- function.
+ go z RMEmpty = z
+ go z rm@(RM{}) =
+ foldr
+ f
+ (foldDNameEnv
+ (flip go)
+ (go z (rm_unknown rm))
+ (rm_known rm)
+ )
+ (rm_empty rm)
+
+nonDetStrictFoldRM :: (b -> a -> b) -> b -> RoughMap a -> b
+nonDetStrictFoldRM f = go
+ where
+ -- N.B. local worker ensures that the loop can be specialised to the fold
+ -- function.
+ go !z RMEmpty = z
+ go z rm@(RM{}) =
+ foldl'
+ f
+ (nonDetStrictFoldDNameEnv
+ (flip go)
+ (go z (rm_unknown rm))
+ (rm_known rm)
+ )
+ (rm_empty rm)
+
+sizeRM :: RoughMap a -> Int
+sizeRM = nonDetStrictFoldRM (\acc _ -> acc + 1) 0
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index 1fae72f2ce..76c39e630b 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -380,6 +380,7 @@ Library
ErrUtils
Finder
GHC
+ RoughMap
GhcMake
GhcPlugins
DynamicLoading
diff --git a/compiler/iface/MkIface.hs b/compiler/iface/MkIface.hs
index 0ae3e4489f..4b9ed5ec8b 100644
--- a/compiler/iface/MkIface.hs
+++ b/compiler/iface/MkIface.hs
@@ -107,6 +107,7 @@ import Maybes
import Binary
import Fingerprint
import Exception
+import RoughMap
import UniqSet
import Packages
import ExtractDocs
@@ -271,7 +272,7 @@ mkIface_ hsc_env maybe_old_fingerprint
-- See Note [Deterministic UniqFM] in UniqDFM for more details.
warns = src_warns
iface_rules = map coreRuleToIfaceRule rules
- iface_insts = map instanceToIfaceInst $ fixSafeInstances safe_mode insts
+ iface_insts = map instanceToIfaceInst $ fixSafeInstances safe_mode (instEnvElts insts)
iface_fam_insts = map famInstToIfaceFamInst fam_insts
trust_info = setSafeMode safe_mode
annotations = map mkIfaceAnnotation anns
@@ -2030,8 +2031,8 @@ instanceToIfaceInst (ClsInst { is_dfun = dfun_id, is_flag = oflag
ifInstTys = map do_rough mb_tcs,
ifInstOrph = orph }
where
- do_rough Nothing = Nothing
- do_rough (Just n) = Just (toIfaceTyCon_name n)
+ do_rough OtherTc = Nothing
+ do_rough (KnownTc n) = Just (toIfaceTyCon_name n)
dfun_name = idName dfun_id
@@ -2046,8 +2047,8 @@ famInstToIfaceFamInst (FamInst { fi_axiom = axiom,
, ifFamInstTys = map do_rough roughs
, ifFamInstOrph = orph }
where
- do_rough Nothing = Nothing
- do_rough (Just n) = Just (toIfaceTyCon_name n)
+ do_rough OtherTc = Nothing
+ do_rough (KnownTc n) = Just (toIfaceTyCon_name n)
fam_decl = tyConName $ coAxiomTyCon axiom
mod = ASSERT( isExternalName (coAxiomName axiom) )
diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs
index 3a55213760..301e09e3c7 100644
--- a/compiler/iface/TcIface.hs
+++ b/compiler/iface/TcIface.hs
@@ -56,13 +56,13 @@ import TysWiredIn
import Literal
import Var
import VarSet
+import RoughMap
import Name
import NameEnv
import NameSet
import OccurAnal ( occurAnalyseExpr )
import Demand
import Module
-import Unify ( RoughMatchTc(..) )
import UniqFM
import UniqSupply
import Outputable
@@ -185,7 +185,7 @@ typecheckIface iface
-- an example where this would cause non-termination.
text "Type envt:" <+> ppr (map fst names_w_things)])
; return $ ModDetails { md_types = type_env
- , md_insts = insts
+ , md_insts = mkInstEnv insts
, md_fam_insts = fam_insts
, md_rules = rules
, md_anns = anns
@@ -391,7 +391,7 @@ typecheckIfacesForMerging mod ifaces tc_env_var =
exports <- ifaceExportNames (mi_exports iface)
complete_sigs <- tcIfaceCompleteSigs (mi_complete_sigs iface)
return $ ModDetails { md_types = type_env
- , md_insts = insts
+ , md_insts = mkInstEnv insts
, md_fam_insts = fam_insts
, md_rules = rules
, md_anns = anns
@@ -430,7 +430,7 @@ typecheckIfaceForInstantiate nsubst iface =
exports <- ifaceExportNames (mi_exports iface)
complete_sigs <- tcIfaceCompleteSigs (mi_complete_sigs iface)
return $ ModDetails { md_types = type_env
- , md_insts = insts
+ , md_insts = mkInstEnv insts
, md_fam_insts = fam_insts
, md_rules = rules
, md_anns = anns
diff --git a/compiler/main/GHC.hs b/compiler/main/GHC.hs
index 756dc82bc1..304043ffd8 100644
--- a/compiler/main/GHC.hs
+++ b/compiler/main/GHC.hs
@@ -935,7 +935,7 @@ typecheckModule pmod = do
minf_type_env = md_types details,
minf_exports = md_exports details,
minf_rdr_env = Just (tcg_rdr_env tc_gbl_env),
- minf_instances = fixSafeInstances safe $ md_insts details,
+ minf_instances = fixSafeInstances safe $ instEnvElts $ md_insts details,
minf_iface = Nothing,
minf_safe = safe,
minf_modBreaks = emptyModBreaks
@@ -1107,7 +1107,8 @@ getBindings = withSession $ \hsc_env ->
-- | Return the instances for the current interactive session.
getInsts :: GhcMonad m => m ([ClsInst], [FamInst])
getInsts = withSession $ \hsc_env ->
- return $ ic_instances (hsc_IC hsc_env)
+ let (inst_env, fam_env) = ic_instances (hsc_IC hsc_env)
+ in return (instEnvElts inst_env, fam_env)
getPrintUnqual :: GhcMonad m => m PrintUnqualified
getPrintUnqual = withSession $ \hsc_env ->
@@ -1174,7 +1175,7 @@ getHomeModuleInfo hsc_env mdl =
minf_type_env = md_types details,
minf_exports = md_exports details,
minf_rdr_env = mi_globals $! hm_iface hmi,
- minf_instances = md_insts details,
+ minf_instances = instEnvElts $ md_insts details,
minf_iface = Just iface,
minf_safe = getSafeMode $ mi_trust iface
,minf_modBreaks = getModBreaks hmi
diff --git a/compiler/main/HscTypes.hs b/compiler/main/HscTypes.hs
index e46574ba05..95ea92bbc5 100644
--- a/compiler/main/HscTypes.hs
+++ b/compiler/main/HscTypes.hs
@@ -159,8 +159,8 @@ import HsSyn
import RdrName
import Avail
import Module
-import InstEnv ( InstEnv, ClsInst, identicalClsInstHead )
import FamInstEnv
+import InstEnv
import CoreSyn ( CoreProgram, RuleBase, CoreRule )
import Name
import NameEnv
@@ -671,13 +671,13 @@ hptCompleteSigs = hptAllThings (md_complete_sigs . hm_details)
-- the Home Package Table filtered by the provided predicate function.
-- Used in @tcRnImports@, to select the instances that are in the
-- transitive closure of imports from the currently compiled module.
-hptInstances :: HscEnv -> (ModuleName -> Bool) -> ([ClsInst], [FamInst])
+hptInstances :: HscEnv -> (ModuleName -> Bool) -> (InstEnv, [FamInst])
hptInstances hsc_env want_this_module
= let (insts, famInsts) = unzip $ flip hptAllThings hsc_env $ \mod_info -> do
guard (want_this_module (moduleName (mi_module (hm_iface mod_info))))
let details = hm_details mod_info
return (md_insts details, md_fam_insts details)
- in (concat insts, concat famInsts)
+ in (foldl' unionInstEnv emptyInstEnv insts, concat famInsts)
-- | Get rules from modules "below" this one (in the dependency sense)
hptRules :: HscEnv -> [(ModuleName, IsBootInterface)] -> [CoreRule]
@@ -1233,7 +1233,7 @@ data ModDetails
md_exports :: [AvailInfo],
md_types :: !TypeEnv, -- ^ Local type environment for this particular module
-- Includes Ids, TyCons, PatSyns
- md_insts :: ![ClsInst], -- ^ 'DFunId's for the instances in this module
+ md_insts :: !InstEnv, -- ^ 'DFunId's for the instances in this module
md_fam_insts :: ![FamInst],
md_rules :: ![CoreRule], -- ^ Domain may include 'Id's from other modules
md_anns :: ![Annotation], -- ^ Annotations present in this module: currently
@@ -1247,7 +1247,7 @@ emptyModDetails :: ModDetails
emptyModDetails
= ModDetails { md_types = emptyTypeEnv,
md_exports = [],
- md_insts = [],
+ md_insts = emptyInstEnv,
md_rules = [],
md_fam_insts = [],
md_anns = [],
@@ -1588,7 +1588,7 @@ data InteractiveContext
-- It contains everything in scope at the command line,
-- including everything in ic_tythings
- ic_instances :: ([ClsInst], [FamInst]),
+ ic_instances :: (InstEnv, [FamInst]),
-- ^ All instances and family instances created during
-- this session. These are grabbed en masse after each
-- update to be sure that proper overlapping is retained.
@@ -1636,7 +1636,7 @@ emptyInteractiveContext dflags
ic_rn_gbl_env = emptyGlobalRdrEnv,
ic_mod_index = 1,
ic_tythings = [],
- ic_instances = ([],[]),
+ ic_instances = (emptyInstEnv,[]),
ic_fix_env = emptyNameEnv,
ic_monad = ioTyConName, -- IO monad by default
ic_int_print = printName, -- System.IO.print by default
@@ -1666,7 +1666,7 @@ icPrintUnqual dflags InteractiveContext{ ic_rn_gbl_env = grenv } =
-- not clear whether removing them is even the appropriate behavior.
extendInteractiveContext :: InteractiveContext
-> [TyThing]
- -> [ClsInst] -> [FamInst]
+ -> InstEnv -> [FamInst]
-> Maybe [Type]
-> FixityEnv
-> InteractiveContext
@@ -1676,7 +1676,7 @@ extendInteractiveContext ictxt new_tythings new_cls_insts new_fam_insts defaults
-- a new mod_index (Trac #9426)
, ic_tythings = new_tythings ++ old_tythings
, ic_rn_gbl_env = ic_rn_gbl_env ictxt `icExtendGblRdrEnv` new_tythings
- , ic_instances = ( new_cls_insts ++ old_cls_insts
+ , ic_instances = ( new_cls_insts `unionInstEnv` old_cls_insts
, new_fam_insts ++ fam_insts )
-- we don't shadow old family instances (#7102),
-- so don't need to remove them here
@@ -1690,7 +1690,7 @@ extendInteractiveContext ictxt new_tythings new_cls_insts new_fam_insts defaults
-- Discard old instances that have been fully overridden
-- See Note [Override identical instances in GHCi]
(cls_insts, fam_insts) = ic_instances ictxt
- old_cls_insts = filterOut (\i -> any (identicalClsInstHead i) new_cls_insts) cls_insts
+ old_cls_insts = filterInstEnv (\i -> not $ anyInstEnv (identicalClsInstHead i) new_cls_insts) cls_insts
extendInteractiveContextWithIds :: InteractiveContext -> [Id] -> InteractiveContext
-- Just a specialised version
diff --git a/compiler/main/TidyPgm.hs b/compiler/main/TidyPgm.hs
index c96a2f2843..392f5fb02a 100644
--- a/compiler/main/TidyPgm.hs
+++ b/compiler/main/TidyPgm.hs
@@ -177,7 +177,7 @@ mkBootModDetailsTc hsc_env
final_tcs = filterOut (isWiredInName . getName) tcs
-- See Note [Drop wired-in things]
type_env1 = typeEnvFromEntities final_ids final_tcs fam_insts
- insts' = mkFinalClsInsts type_env1 insts
+ insts' = mkFinalClsInsts type_env1 (mkInstEnv insts)
pat_syns' = mkFinalPatSyns type_env1 pat_syns
type_env' = extendTypeEnvWithPatSyns pat_syns' type_env1
@@ -200,8 +200,8 @@ lookupFinalId type_env id
Just (AnId id') -> id'
_ -> pprPanic "lookup_final_id" (ppr id)
-mkFinalClsInsts :: TypeEnv -> [ClsInst] -> [ClsInst]
-mkFinalClsInsts env = map (updateClsInstDFun (lookupFinalId env))
+mkFinalClsInsts :: TypeEnv -> InstEnv -> InstEnv
+mkFinalClsInsts env = updateClsInstDFuns (lookupFinalId env)
mkFinalPatSyns :: TypeEnv -> [PatSyn] -> [PatSyn]
mkFinalPatSyns env = map (updatePatSynIds (lookupFinalId env))
@@ -391,7 +391,7 @@ tidyProgram hsc_env (ModGuts { mg_module = mod
; final_tcs = filterOut (isWiredInName . getName) tcs
-- See Note [Drop wired-in things]
; type_env = typeEnvFromEntities final_ids final_tcs fam_insts
- ; tidy_cls_insts = mkFinalClsInsts type_env cls_insts
+ ; tidy_cls_insts = mkFinalClsInsts type_env (mkInstEnv cls_insts)
; tidy_patsyns = mkFinalPatSyns type_env patsyns
; tidy_type_env = extendTypeEnvWithPatSyns tidy_patsyns type_env
; tidy_rules = tidyRules tidy_env trimmed_rules
diff --git a/compiler/typecheck/FunDeps.hs b/compiler/typecheck/FunDeps.hs
index cc8bd72569..751a025607 100644
--- a/compiler/typecheck/FunDeps.hs
+++ b/compiler/typecheck/FunDeps.hs
@@ -32,6 +32,7 @@ import FamInst( injTyVarsOfTypes )
import InstEnv
import VarSet
import VarEnv
+import RoughMap
import Outputable
import ErrUtils( Validity(..), allValid )
import SrcLoc
@@ -206,7 +207,7 @@ improveFromInstEnv inst_env mk_loc pred
getClassPredTys_maybe pred
, let (cls_tvs, cls_fds) = classTvsFds cls
instances = classInstances inst_env cls
- rough_tcs = roughMatchTcs tys
+ rough_tcs = KnownTc (className cls) : roughMatchTcs tys
= [ FDEqn { fd_qtvs = meta_tvs, fd_eqs = eqs
, fd_pred1 = p_inst, fd_pred2 = pred
, fd_loc = mk_loc p_inst (getSrcSpan (is_dfun ispec)) }
@@ -668,8 +669,9 @@ trimRoughMatchTcs :: [TyVar] -> FunDep TyVar -> [RoughMatchTc] -> [RoughMatchTc]
-- Hence, we Nothing-ise the tb and tc types right here
--
-- Result list is same length as input list, just with more Nothings
-trimRoughMatchTcs clas_tvs (ltvs, _) mb_tcs
- = zipWith select clas_tvs mb_tcs
+trimRoughMatchTcs _clas_tvs _ [] = panic "trimRoughMatchTcs: nullary [RoughMatchTc]"
+trimRoughMatchTcs clas_tvs (ltvs, _) (cls:mb_tcs)
+ = cls : zipWith select clas_tvs mb_tcs
where
select clas_tv mb_tc | clas_tv `elem` ltvs = mb_tc
| otherwise = OtherTc
diff --git a/compiler/typecheck/TcBackpack.hs b/compiler/typecheck/TcBackpack.hs
index 7fffcd1d18..91dfb277ff 100644
--- a/compiler/typecheck/TcBackpack.hs
+++ b/compiler/typecheck/TcBackpack.hs
@@ -125,7 +125,7 @@ checkHsigIface tcg_env gr sig_iface
tcg_fam_inst_env = emptyFamInstEnv,
tcg_insts = [],
tcg_fam_insts = [] } $ do
- mapM_ check_inst sig_insts
+ mapM_ check_inst (instEnvElts sig_insts)
failIfErrsM
where
-- NB: the Names in sig_type_env are bogus. Let's say we have H.hsig
@@ -135,7 +135,7 @@ checkHsigIface tcg_env gr sig_iface
sig_type_occ_env = mkOccEnv
. map (\t -> (nameOccName (getName t), t))
$ nameEnvElts sig_type_env
- dfun_names = map getName sig_insts
+ dfun_names = map getName (instEnvElts sig_insts)
check_export name
-- Skip instances, we'll check them later
-- TODO: Actually this should never happen, because DFuns are
@@ -828,7 +828,7 @@ mergeSignatures
= (inst:insts, extendInstEnv inst_env inst)
(insts, inst_env) = foldl' merge_inst
(tcg_insts tcg_env, tcg_inst_env tcg_env)
- (md_insts details)
+ (instEnvElts $ md_insts details)
-- This is a HACK to prevent calculateAvails from including imp_mod
-- in the listing. We don't want it because a module is NOT
-- supposed to include itself in its dep_orphs/dep_finsts. See #13214
diff --git a/compiler/typecheck/TcRnDriver.hs b/compiler/typecheck/TcRnDriver.hs
index beb630e844..d673fc8848 100644
--- a/compiler/typecheck/TcRnDriver.hs
+++ b/compiler/typecheck/TcRnDriver.hs
@@ -54,6 +54,7 @@ import IfaceEnv( externaliseName )
import TcHsType
import TcValidity( checkValidType )
import TcMatches
+import RoughMap
import Inst( deeplyInstantiate )
import TcUnify( checkConstraints )
import RnTypes
@@ -109,7 +110,6 @@ import IdInfo( IdDetails(..) )
import VarEnv
import Module
import UniqFM
-import Unify ( RoughMatchTc(..) )
import Name
import NameEnv
import NameSet
@@ -348,7 +348,7 @@ tcRnImports hsc_env import_decls
tcg_rdr_env = tcg_rdr_env gbl `plusGlobalRdrEnv` rdr_env,
tcg_imports = tcg_imports gbl `plusImportAvails` imports,
tcg_rn_imports = rn_imports,
- tcg_inst_env = extendInstEnvList (tcg_inst_env gbl) home_insts,
+ tcg_inst_env = tcg_inst_env gbl `unionInstEnv` home_insts,
tcg_fam_inst_env = extendFamInstEnvList (tcg_fam_inst_env gbl)
home_fam_insts,
tcg_hpc = hpc_info
@@ -1841,7 +1841,7 @@ runTcInteractive hsc_env thing_inside
= initTcInteractive hsc_env $ withTcPlugins hsc_env $
do { traceTc "setInteractiveContext" $
vcat [ text "ic_tythings:" <+> vcat (map ppr (ic_tythings icxt))
- , text "ic_insts:" <+> vcat (map (pprBndr LetBind . instanceDFunId) ic_insts)
+ , text "ic_insts:" <+> vcat (map (pprBndr LetBind . instanceDFunId) (instEnvElts ic_insts))
, text "ic_rn_gbl_env (LocalDef)" <+>
vcat (map ppr [ local_gres | gres <- occEnvElts (ic_rn_gbl_env icxt)
, let local_gres = filter isLocalGRE gres
@@ -1867,9 +1867,7 @@ runTcInteractive hsc_env thing_inside
; let gbl_env' = gbl_env {
tcg_rdr_env = ic_rn_gbl_env icxt
, tcg_type_env = type_env
- , tcg_inst_env = extendInstEnvList
- (extendInstEnvList (tcg_inst_env gbl_env) ic_insts)
- home_insts
+ , tcg_inst_env = tcg_inst_env gbl_env `unionInstEnv` ic_insts `unionInstEnv` home_insts
, tcg_fam_inst_env = extendFamInstEnvList
(extendFamInstEnvList (tcg_fam_inst_env gbl_env)
ic_finsts)
@@ -1906,7 +1904,7 @@ runTcInteractive hsc_env thing_inside
= Right thing
type_env1 = mkTypeEnvWithImplicits top_ty_things
- type_env = extendTypeEnvWithIds type_env1 (map instanceDFunId ic_insts)
+ type_env = extendTypeEnvWithIds type_env1 (map instanceDFunId (instEnvElts ic_insts))
-- Putting the dfuns in the type_env
-- is just to keep Core Lint happy
diff --git a/compiler/types/FamInstEnv.hs b/compiler/types/FamInstEnv.hs
index 269435f5d3..2eefe03a11 100644
--- a/compiler/types/FamInstEnv.hs
+++ b/compiler/types/FamInstEnv.hs
@@ -13,7 +13,7 @@ module FamInstEnv (
-- * Family instance environment
FamInstEnvs, FamInstEnv, emptyFamInstEnv, emptyFamInstEnvs,
- extendFamInstEnv, extendFamInstEnvList,
+ unionFamInstEnv, extendFamInstEnv, extendFamInstEnvList,
famInstEnvElts, famInstEnvSize, familyInstances,
-- * CoAxioms
@@ -53,10 +53,10 @@ import VarSet
import VarEnv
import Name
import PrelNames ( eqPrimTyConKey )
-import UniqDFM
import Outputable
import Maybes
import CoreMap
+import RoughMap
import Unique
import Util
import Var
@@ -108,8 +108,7 @@ data FamInst -- See Note [FamInsts and CoAxioms]
, fi_fam :: Name -- Family name
-- Used for "rough matching"; same idea as for class instances
- -- See Note [Rough matching in class and family instances]
- -- in GHC.Core.Unify
+ -- See Note [Rough-match field] in InstEnv
, fi_tcs :: [RoughMatchTc] -- Top of type args
-- INVARIANT: fi_tcs = roughMatchTcs fi_tys
@@ -305,7 +304,12 @@ mkImportedFamInst fam mb_tcs axiom
Note [FamInstEnv]
~~~~~~~~~~~~~~~~~
-A FamInstEnv maps a family name to the list of known instances for that family.
+A FamInstEnv is a RoughMap of instance heads. Specifically, the keys are formed
+by the family name and the instance arguments. That is, an instance:
+
+ type instance Fam (Maybe Int) a
+
+would give rise to a key of the form [KnownTc Fam, KnownTc Maybe, UnknownTc]
The same FamInstEnv includes both 'data family' and 'type family' instances.
Type families are reduced during type inference, but not data families;
@@ -353,19 +357,22 @@ UniqFM and UniqDFM.
See Note [Deterministic UniqFM].
-}
-type FamInstEnv = UniqDFM FamilyInstEnv -- ^ Maps a family to its instances
+type FamInstEnvs = (FamInstEnv, FamInstEnv)
+ -- External package inst-env, Home-package inst-env
+
+data FamInstEnv
+ = FamIE !Int !(RoughMap FamInst)
-- See Note [FamInstEnv]
-- See Note [FamInstEnv determinism]
-type FamInstEnvs = (FamInstEnv, FamInstEnv)
- -- External package inst-env, Home-package inst-env
-newtype FamilyInstEnv
- = FamIE [FamInst] -- The instances for a particular family, in any order
+instance Outputable FamInstEnv where
+ ppr (FamIE _ fs) = text "FamIE" <+> vcat (map ppr $ elemsRM fs)
-instance Outputable FamilyInstEnv where
- ppr (FamIE fs) = text "FamIE" <+> vcat (map ppr fs)
+famInstEnvSize :: FamInstEnv -> Int
+famInstEnvSize (FamIE sz _) = sz
+-- | Create a 'FamInstEnv' from 'Name' indices.
-- INVARIANTS:
-- * The fs_tvs are distinct in each FamInst
-- of a range value of the map (so we can safely unify them)
@@ -374,34 +381,36 @@ emptyFamInstEnvs :: (FamInstEnv, FamInstEnv)
emptyFamInstEnvs = (emptyFamInstEnv, emptyFamInstEnv)
emptyFamInstEnv :: FamInstEnv
-emptyFamInstEnv = emptyUDFM
+emptyFamInstEnv = FamIE 0 emptyRM
famInstEnvElts :: FamInstEnv -> [FamInst]
-famInstEnvElts fi = [elt | FamIE elts <- eltsUDFM fi, elt <- elts]
+famInstEnvElts (FamIE _ rm) = elemsRM rm
-- See Note [FamInstEnv determinism]
-famInstEnvSize :: FamInstEnv -> Int
-famInstEnvSize = nonDetFoldUDFM (\(FamIE elt) sum -> sum + length elt) 0
- -- It's OK to use nonDetFoldUDFM here since we're just computing the
+ -- It's OK to use nonDetStrictFoldUDFM here since we're just computing the
-- size.
familyInstances :: (FamInstEnv, FamInstEnv) -> TyCon -> [FamInst]
familyInstances (pkg_fie, home_fie) fam
= get home_fie ++ get pkg_fie
where
- get env = case lookupUDFM env fam of
- Just (FamIE insts) -> insts
- Nothing -> []
+ get :: FamInstEnv -> [FamInst]
+ get (FamIE _ env) = lookupRM [KnownTc (tyConName fam)] env
+
+
+-- | Makes no particular effort to detect conflicts.
+unionFamInstEnv :: FamInstEnv -> FamInstEnv -> FamInstEnv
+unionFamInstEnv (FamIE sa a) (FamIE sb b) = FamIE (sa + sb) (a `unionRM` b)
extendFamInstEnvList :: FamInstEnv -> [FamInst] -> FamInstEnv
extendFamInstEnvList inst_env fis = foldl' extendFamInstEnv inst_env fis
extendFamInstEnv :: FamInstEnv -> FamInst -> FamInstEnv
-extendFamInstEnv inst_env
+extendFamInstEnv (FamIE s inst_env)
ins_item@(FamInst {fi_fam = cls_nm})
- = addToUDFM_C add inst_env cls_nm (FamIE [ins_item])
+ = FamIE (s+1) $ insertRM rough_tmpl ins_item inst_env
where
- add (FamIE items) _ = FamIE (ins_item:items)
+ rough_tmpl = KnownTc cls_nm : fi_tcs ins_item
{-
************************************************************************
@@ -763,9 +772,7 @@ lookupFamInstEnvByTyCon :: FamInstEnvs -> TyCon -> [FamInst]
lookupFamInstEnvByTyCon (pkg_ie, home_ie) fam_tc
= get pkg_ie ++ get home_ie
where
- get ie = case lookupUDFM ie fam_tc of
- Nothing -> []
- Just (FamIE fis) -> fis
+ get (FamIE _ rm) = lookupRM [KnownTc (tyConName fam_tc)] rm
-- | Look-up an instance for a type family applied to some types.
lookupFamInstEnv
@@ -910,11 +917,17 @@ lookupFamInstEnvInjectivityConflicts
-> FamInstEnvs -- all type instances seens so far
-> FamInst -- new type instance that we're checking
-> [CoAxBranch] -- conflicting instance declarations
-lookupFamInstEnvInjectivityConflicts injList (pkg_ie, home_ie)
+lookupFamInstEnvInjectivityConflicts injList fam_inst_envs
fam_inst@(FamInst { fi_axiom = new_axiom })
+ | not $ isOpenFamilyTyCon fam
+ = []
+
+ | otherwise
-- See Note [Verifying injectivity annotation]. This function implements
-- check (1.B1) for open type families described there.
- = lookup_inj_fam_conflicts home_ie ++ lookup_inj_fam_conflicts pkg_ie
+ = map (coAxiomSingleBranch . fi_axiom) $
+ filter isInjConflict $
+ familyInstances fam_inst_envs fam
where
fam = famInstTyCon fam_inst
new_branch = coAxiomSingleBranch new_axiom
@@ -927,12 +940,6 @@ lookupFamInstEnvInjectivityConflicts injList (pkg_ie, home_ie)
= False -- no conflict
| otherwise = True
- lookup_inj_fam_conflicts ie
- | isOpenFamilyTyCon fam, Just (FamIE insts) <- lookupUDFM ie fam
- = map (coAxiomSingleBranch . fi_axiom) $
- filter isInjConflict insts
- | otherwise = []
-
--------------------------------------------------------------------------------
-- Type family overlap checking bits --
@@ -961,37 +968,47 @@ type MatchFun = FamInst -- The FamInst template
-> [Type] -- Target to match against
-> Maybe TCvSubst
+mapMaybe' :: Foldable f => (a -> Maybe b) -> f a -> [b]
+mapMaybe' f = foldr g []
+ where
+ g x rest
+ | Just y <- f x = y : rest
+ | otherwise = rest
+
lookup_fam_inst_env' -- The worker, local to this module
:: MatchFun
-> FamInstEnv
-> TyCon -> [Type] -- What we are looking for
-> [FamInstMatch]
-lookup_fam_inst_env' match_fun ie fam match_tys
+lookup_fam_inst_env' match_fun (FamIE _ ie) fam match_tys
| isOpenFamilyTyCon fam
- , Just (FamIE insts) <- lookupUDFM ie fam
- = find insts -- The common case
+ , let xs = (lookupRM' rough_tmpl ie) -- The common case
+ -- Avoid doing any of the allocation below if there are no instances to look at.
+ , not $ null xs
+ = mapMaybe' f xs
| otherwise = []
where
+ rough_tmpl :: [RoughMatchTc]
+ rough_tmpl = KnownTc (tyConName fam) : map typeToRoughMatchTc match_tys
- find [] = []
- find (item@(FamInst { fi_tcs = mb_tcs, fi_tvs = tpl_tvs, fi_cvs = tpl_cvs
- , fi_tys = tpl_tys }) : rest)
+ f :: FamInst -> Maybe FamInstMatch
+ f item@(FamInst { fi_tcs = mb_tcs, fi_tvs = tpl_tvs, fi_cvs = tpl_cvs
+ , fi_tys = tpl_tys })
-- Fast check for no match, uses the "rough match" fields
| instanceCantMatch rough_tcs mb_tcs
- = find rest
+ = Nothing
-- Proper check
| Just subst <- match_fun item (mkVarSet tpl_tvs) tpl_tys match_tys1
- = (FamInstMatch { fim_instance = item
- , fim_tys = substTyVars subst tpl_tvs `chkAppend` match_tys2
- , fim_cos = ASSERT( all (isJust . lookupCoVar subst) tpl_cvs )
- substCoVars subst tpl_cvs
- })
- : find rest
+ = Just (FamInstMatch { fim_instance = item
+ , fim_tys = substTyVars subst tpl_tvs `chkAppend` match_tys2
+ , fim_cos = ASSERT( all (isJust . lookupCoVar subst) tpl_cvs )
+ substCoVars subst tpl_cvs
+ })
-- No match => try next
| otherwise
- = find rest
+ = Nothing
where
(rough_tcs, match_tys1, match_tys2) = split_tys tpl_tys
diff --git a/compiler/types/InstEnv.hs b/compiler/types/InstEnv.hs
index 64e9378fd9..04d77cc56d 100644
--- a/compiler/types/InstEnv.hs
+++ b/compiler/types/InstEnv.hs
@@ -14,12 +14,13 @@ module InstEnv (
OverlapFlag(..), OverlapMode(..), setOverlapModeMaybe,
ClsInst(..), DFunInstType, pprInstance, pprInstanceHdr, pprInstances,
instanceHead, instanceSig, mkLocalInstance, mkImportedInstance,
- instanceDFunId, updateClsInstDFun, instanceRoughTcs,
+ instanceDFunId, updateClsInstDFun, updateClsInstDFuns,
fuzzyClsInstCmp, orphNamesOfClsInst,
InstEnvs(..), VisibleOrphanModules, InstEnv,
- emptyInstEnv, extendInstEnv,
- deleteFromInstEnv, deleteDFunFromInstEnv,
+ mkInstEnv, emptyInstEnv, unionInstEnv, extendInstEnv,
+ filterInstEnv, deleteFromInstEnv, deleteDFunFromInstEnv,
+ anyInstEnv,
identicalClsInstHead,
extendInstEnvList, lookupUniqueInstEnv, lookupInstEnv, instEnvElts,
memberInstEnv,
@@ -45,8 +46,8 @@ import NameSet
import Unify
import Outputable
import ErrUtils
+import RoughMap
import BasicTypes
-import UniqDFM
import Util
import Id
import Data.Data ( Data )
@@ -66,7 +67,7 @@ import Data.Maybe ( isJust )
data ClsInst
= ClsInst { -- Used for "rough matching"; see
-- Note [ClsInst laziness and the rough-match fields]
- -- INVARIANT: is_tcs = roughMatchTcs is_tys
+ -- INVARIANT: is_tcs = KnownTc is_cls_nm : roughMatchTcs is_tys
is_cls_nm :: Name -- ^ Class name
, is_tcs :: [RoughMatchTc] -- ^ Top of type args
@@ -101,8 +102,7 @@ data ClsInst
-- instances before displaying them to the user.
fuzzyClsInstCmp :: ClsInst -> ClsInst -> Ordering
fuzzyClsInstCmp x y =
- stableNameCmp (is_cls_nm x) (is_cls_nm y) `mappend`
- mconcat (map cmp (zip (is_tcs x) (is_tcs y)))
+ foldMap cmp (zip (is_tcs x) (is_tcs y))
where
cmp (OtherTc, OtherTc) = EQ
cmp (OtherTc, KnownTc _) = LT
@@ -194,9 +194,9 @@ updateClsInstDFun :: (DFunId -> DFunId) -> ClsInst -> ClsInst
updateClsInstDFun tidy_dfun ispec
= ispec { is_dfun = tidy_dfun (is_dfun ispec) }
-instanceRoughTcs :: ClsInst -> [RoughMatchTc]
-instanceRoughTcs = is_tcs
-
+updateClsInstDFuns :: (DFunId -> DFunId) -> InstEnv -> InstEnv
+updateClsInstDFuns tidy_dfun (InstEnv rm)
+ = InstEnv $ fmap (updateClsInstDFun tidy_dfun) rm
instance NamedThing ClsInst where
getName ispec = getName (is_dfun ispec)
@@ -258,7 +258,7 @@ mkLocalInstance dfun oflag tvs cls tys
, is_tvs = tvs
, is_dfun_name = dfun_name
, is_cls = cls, is_cls_nm = cls_name
- , is_tys = tys, is_tcs = roughMatchTcs tys
+ , is_tys = tys, is_tcs = KnownTc cls_name : roughMatchTcs tys
, is_orphan = orph
}
where
@@ -289,7 +289,7 @@ mkLocalInstance dfun oflag tvs cls tys
choose_one nss = chooseOrphanAnchor (unionNameSets nss)
mkImportedInstance :: Name -- ^ the name of the class
- -> [RoughMatchTc] -- ^ the types which the class was applied to
+ -> [RoughMatchTc] -- ^ the rough match signature of the instance
-> Name -- ^ the 'Name' of the dictionary binding
-> DFunId -- ^ the 'Id' of the dictionary.
-> OverlapFlag -- ^ may this instance overlap?
@@ -376,9 +376,21 @@ Testing with nofib and validate detected no difference between UniqFM and
UniqDFM. See also Note [Deterministic UniqFM]
-}
-type InstEnv = UniqDFM ClsInstEnv -- Maps Class to instances for that class
+-- Internally it's safe to indexable this map by
+-- by @Class@, the classes @Name@, the classes @TyCon@
+-- or it's @Unique@.
+-- This is since:
+-- getUnique cls == getUnique (className cls) == getUnique (classTyCon cls)
+--
+-- We still use Class as key type as it's both the common case
+-- and conveys the meaning better. But the implementation of
+--InstEnv is a bit more lax internally.
+newtype InstEnv = InstEnv (RoughMap ClsInst) -- Maps Class to instances for that class
-- See Note [InstEnv determinism]
+instance Outputable InstEnv where
+ ppr (InstEnv rm) = pprInstances $ elemsRM rm
+
-- | 'InstEnvs' represents the combination of the global type class instance
-- environment, the local type class instance environment, and the set of
-- transitively reachable orphan modules (according to what modules have been
@@ -396,28 +408,29 @@ data InstEnvs = InstEnvs {
-- transitively reachable orphan modules (modules that define orphan instances).
type VisibleOrphanModules = ModuleSet
-newtype ClsInstEnv
- = ClsIE [ClsInst] -- The instances for a particular class, in any order
-
-instance Outputable ClsInstEnv where
- ppr (ClsIE is) = pprInstances is
-- INVARIANTS:
-- * The is_tvs are distinct in each ClsInst
-- of a ClsInstEnv (so we can safely unify them)
--- Thus, the @ClassInstEnv@ for @Eq@ might contain the following entry:
+-- Thus, the @ClsInstEnv@ for @Eq@ might contain the following entry:
-- [a] ===> dfun_Eq_List :: forall a. Eq a => Eq [a]
-- The "a" in the pattern must be one of the forall'd variables in
-- the dfun type.
emptyInstEnv :: InstEnv
-emptyInstEnv = emptyUDFM
+emptyInstEnv = InstEnv emptyRM
+
+mkInstEnv :: [ClsInst] -> InstEnv
+mkInstEnv = extendInstEnvList emptyInstEnv
instEnvElts :: InstEnv -> [ClsInst]
-instEnvElts ie = [elt | ClsIE elts <- eltsUDFM ie, elt <- elts]
+instEnvElts (InstEnv rm) = elemsRM rm
-- See Note [InstEnv determinism]
+instEnvEltsForClass :: InstEnv -> Class -> [ClsInst]
+instEnvEltsForClass (InstEnv rm) cls = lookupRM [KnownTc (className cls)] rm
+
-- | Test if an instance is visible, by checking that its origin module
-- is in 'VisibleOrphanModules'.
-- See Note [Instance lookup and orphan instances]
@@ -436,53 +449,58 @@ classInstances :: InstEnvs -> Class -> [ClsInst]
classInstances (InstEnvs { ie_global = pkg_ie, ie_local = home_ie, ie_visible = vis_mods }) cls
= get home_ie ++ get pkg_ie
where
- get env = case lookupUDFM env cls of
- Just (ClsIE insts) -> filter (instIsVisible vis_mods) insts
- Nothing -> []
+ get :: InstEnv -> [ClsInst]
+ get ie = filter (instIsVisible vis_mods) (instEnvEltsForClass ie cls)
-- | Checks for an exact match of ClsInst in the instance environment.
-- We use this when we do signature checking in TcRnDriver
memberInstEnv :: InstEnv -> ClsInst -> Bool
-memberInstEnv inst_env ins_item@(ClsInst { is_cls_nm = cls_nm } ) =
- maybe False (\(ClsIE items) -> any (identicalDFunType ins_item) items)
- (lookupUDFM inst_env cls_nm)
+memberInstEnv (InstEnv rm) ins_item@(ClsInst { is_tcs = tcs } ) =
+ any (identicalDFunType ins_item) (lookupRM' tcs rm)
where
identicalDFunType cls1 cls2 =
eqType (varType (is_dfun cls1)) (varType (is_dfun cls2))
+-- | Makes no particular effort to detect conflicts.
+unionInstEnv :: InstEnv -> InstEnv -> InstEnv
+unionInstEnv (InstEnv a) (InstEnv b) = InstEnv (a `unionRM` b)
+
extendInstEnvList :: InstEnv -> [ClsInst] -> InstEnv
extendInstEnvList inst_env ispecs = foldl' extendInstEnv inst_env ispecs
extendInstEnv :: InstEnv -> ClsInst -> InstEnv
-extendInstEnv inst_env ins_item@(ClsInst { is_cls_nm = cls_nm })
- = addToUDFM_C add inst_env cls_nm (ClsIE [ins_item])
- where
- add (ClsIE cur_insts) _ = ClsIE (ins_item : cur_insts)
+extendInstEnv (InstEnv rm) ins_item@(ClsInst { is_tcs = tcs })
+ = InstEnv $ insertRM tcs ins_item rm
+
+filterInstEnv :: (ClsInst -> Bool) -> InstEnv -> InstEnv
+filterInstEnv pred (InstEnv rm)
+ = InstEnv $ filterRM pred rm
+
+anyInstEnv :: (ClsInst -> Bool) -> InstEnv -> Bool
+anyInstEnv pred (InstEnv rm)
+ = foldRM (\x rest -> pred x || rest) False rm
deleteFromInstEnv :: InstEnv -> ClsInst -> InstEnv
-deleteFromInstEnv inst_env ins_item@(ClsInst { is_cls_nm = cls_nm })
- = adjustUDFM adjust inst_env cls_nm
- where
- adjust (ClsIE items) = ClsIE (filterOut (identicalClsInstHead ins_item) items)
+deleteFromInstEnv (InstEnv rm) ins_item@(ClsInst { is_tcs = tcs })
+ = InstEnv $ filterMatchingRM (not . identicalClsInstHead ins_item) tcs rm
deleteDFunFromInstEnv :: InstEnv -> DFunId -> InstEnv
-- Delete a specific instance fron an InstEnv
-deleteDFunFromInstEnv inst_env dfun
- = adjustUDFM adjust inst_env cls
+deleteDFunFromInstEnv (InstEnv rm) dfun
+ = InstEnv $ filterMatchingRM (not . same_dfun) [KnownTc (className cls)] rm
where
(_, _, cls, _) = tcSplitDFunTy (idType dfun)
- adjust (ClsIE items) = ClsIE (filterOut same_dfun items)
same_dfun (ClsInst { is_dfun = dfun' }) = dfun == dfun'
identicalClsInstHead :: ClsInst -> ClsInst -> Bool
-- ^ True when when the instance heads are the same
-- e.g. both are Eq [(a,b)]
-- Used for overriding in GHCi
--- Obviously should be insenstive to alpha-renaming
-identicalClsInstHead (ClsInst { is_cls_nm = cls_nm1, is_tcs = rough1, is_tys = tys1 })
- (ClsInst { is_cls_nm = cls_nm2, is_tcs = rough2, is_tys = tys2 })
- = cls_nm1 == cls_nm2
- && not (instanceCantMatch rough1 rough2) -- Fast check for no match, uses the "rough match" fields
+-- Obviously should be insensitive to alpha-renaming
+identicalClsInstHead (ClsInst { is_tcs = rough1, is_tys = tys1 })
+ (ClsInst { is_tcs = rough2, is_tys = tys2 })
+ = not (instanceCantMatch rough1 rough2) -- Fast check for no match, uses the "rough match" fields;
+ -- also accounts for class name.
&& isJust (tcMatchTys tys1 tys2)
&& isJust (tcMatchTys tys2 tys1)
@@ -771,35 +789,25 @@ lookupInstEnv' :: InstEnv -- InstEnv to look in
-- but Foo [Int] is a unifier. This gives the caller a better chance of
-- giving a suitable error message
-lookupInstEnv' ie vis_mods cls tys
- = lookup ie
+lookupInstEnv' (InstEnv rm) vis_mods cls tys
+ = foldl' f ([], []) (lookupRM' rough_tcs rm)
where
- rough_tcs = roughMatchTcs tys
+ rough_tcs = KnownTc (className cls) : roughMatchTcs tys
--------------
- lookup env = case lookupUDFM env cls of
- Nothing -> ([],[]) -- No instances for this class
- Just (ClsIE insts) -> find [] [] insts
-
- --------------
- find ms us [] = (ms, us)
- find ms us (item@(ClsInst { is_tcs = mb_tcs, is_tvs = tpl_tvs
- , is_tys = tpl_tys }) : rest)
+ f :: ([InstMatch], [ClsInst]) -> ClsInst -> ([InstMatch], [ClsInst])
+ f acc@(ms, us) item@(ClsInst { is_tvs = tpl_tvs, is_tys = tpl_tys })
| not (instIsVisible vis_mods item)
- = find ms us rest -- See Note [Instance lookup and orphan instances]
-
- -- Fast check for no match, uses the "rough match" fields
- | instanceCantMatch rough_tcs mb_tcs
- = find ms us rest
+ = acc -- See Note [Instance lookup and orphan instances]
| Just subst <- tcMatchTys tpl_tys tys
- = find ((item, map (lookupTyVar subst) tpl_tvs) : ms) us rest
+ = ((item, map (lookupTyVar subst) tpl_tvs) : ms, us)
-- Does not match, so next check whether the things unify
-- See Note [Overlapping instances]
-- Ignore ones that are incoherent: Note [Incoherent instances]
| isIncoherent item
- = find ms us rest
+ = acc
| otherwise
= ASSERT2( tyCoVarsOfTypes tys `disjointVarSet` tpl_tv_set,
@@ -810,8 +818,8 @@ lookupInstEnv' ie vis_mods cls tys
-- They shouldn't because we allocate separate uniques for them
-- See Note [Template tyvars are fresh]
case tcUnifyTys instanceBindFun tpl_tys tys of
- Just _ -> find ms (item:us) rest
- Nothing -> find ms us rest
+ Just _ -> (ms, item:us)
+ Nothing -> acc
where
tpl_tv_set = mkVarSet tpl_tvs
@@ -830,8 +838,7 @@ lookupInstEnv check_overlap_safe
, ie_visible = vis_mods })
cls
tys
- = -- pprTrace "lookupInstEnv" (ppr cls <+> ppr tys $$ ppr home_ie) $
- (final_matches, final_unifs, unsafe_overlapped)
+ = (final_matches, final_unifs, unsafe_overlapped)
where
(home_matches, home_unifs) = lookupInstEnv' home_ie vis_mods cls tys
(pkg_matches, pkg_unifs) = lookupInstEnv' pkg_ie vis_mods cls tys
diff --git a/compiler/types/Unify.hs b/compiler/types/Unify.hs
index d3ea9589e9..0e12d3f160 100644
--- a/compiler/types/Unify.hs
+++ b/compiler/types/Unify.hs
@@ -2,7 +2,7 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE CPP #-}
-{-# LANGUAGE DeriveFunctor, DeriveDataTypeable #-}
+{-# LANGUAGE DeriveFunctor #-}
module Unify (
tcMatchTy, tcMatchTyKi,
@@ -11,8 +11,8 @@ module Unify (
tcMatchTyX_BM, ruleMatchTyKiX,
-- * Rough matching
- RoughMatchTc(..), roughMatchTcs, instanceCantMatch,
- typesCantMatch, isRoughOtherTc,
+ roughMatchTcs, instanceCantMatch,
+ typesCantMatch,
-- Side-effect free unification
tcUnifyTy, tcUnifyTyKi, tcUnifyTys, tcUnifyTyKis,
@@ -37,13 +37,13 @@ import Coercion hiding ( getCvSubstEnv )
import TyCon
import TyCoRep hiding ( getTvSubstEnv, getCvSubstEnv )
import FV( FV, fvVarSet, fvVarList )
+import RoughMap
import Util
import Pair
import Outputable
import UniqFM
import UniqSet
-import Data.Data ( Data )
import Control.Monad
import qualified Control.Monad.Fail as MonadFail
import Control.Applicative hiding ( empty )
@@ -227,59 +227,10 @@ matchBindFun tvs tv = if tv `elemVarSet` tvs then BindMe else Skolem
* *
********************************************************************* -}
-{- Note [Rough matching in class and family instances]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider
- instance C (Maybe [Tree a]) Bool
-and suppose we are looking up
- C Bool Bool
-
-We can very quickly rule the instance out, because the first
-argument is headed by Maybe, whereas in the constraint we are looking
-up has first argument headed by Bool. These "headed by" TyCons are
-called the "rough match TyCons" of the constraint or instance.
-They are used for a quick filter, to check when an instance cannot
-possibly match.
-
-The main motivation is to avoid sucking in whole instance
-declarations that are utterly useless. See GHC.Core.InstEnv
-Note [ClsInst laziness and the rough-match fields].
-
-INVARIANT: a rough-match TyCons `tc` is always a real, generative tycon,
-like Maybe or Either, including a newtype or a data family, both of
-which are generative. It replies True to `isGenerativeTyCon tc Nominal`.
-
-But it is never
- - A type synonym
- E.g. Int and (S Bool) might match
- if (S Bool) is a synonym for Int
-
- - A type family (#19336)
- E.g. (Just a) and (F a) might match if (F a) reduces to (Just a)
- albeit perhaps only after 'a' is instantiated.
--}
-
-data RoughMatchTc
- = KnownTc Name -- INVARIANT: Name refers to a TyCon tc that responds
- -- true to `isGenerativeTyCon tc Nominal`. See
- -- Note [Rough matching in class and family instances]
- | OtherTc -- e.g. type variable at the head
- deriving( Data )
-
-isRoughOtherTc :: RoughMatchTc -> Bool
-isRoughOtherTc OtherTc = True
-isRoughOtherTc (KnownTc {}) = False
+-- See Note [Rough match] field in InstEnv
roughMatchTcs :: [Type] -> [RoughMatchTc]
-roughMatchTcs tys = map rough tys
- where
- rough ty
- | Just (ty', _) <- splitCastTy_maybe ty = rough ty'
- | Just (tc,_) <- splitTyConApp_maybe ty
- , not (isTypeFamilyTyCon tc) = ASSERT2( isGenerativeTyCon tc Nominal, ppr tc )
- KnownTc (tyConName tc)
- -- See Note [Rough matching in class and family instances]
- | otherwise = OtherTc
+roughMatchTcs tys = map typeToRoughMatchTc tys
instanceCantMatch :: [RoughMatchTc] -> [RoughMatchTc] -> Bool
-- (instanceCantMatch tcs1 tcs2) returns True if tcs1 cannot
diff --git a/compiler/utils/Bag.hs b/compiler/utils/Bag.hs
index 5b2c6d56f6..cf7bd123b3 100644
--- a/compiler/utils/Bag.hs
+++ b/compiler/utils/Bag.hs
@@ -6,7 +6,7 @@
Bag: an unordered collection with duplicates
-}
-{-# LANGUAGE ScopedTypeVariables, CPP #-}
+{-# LANGUAGE ScopedTypeVariables, CPP, BangPatterns #-}
module Bag (
Bag, -- abstract type
@@ -33,6 +33,7 @@ import Util
import MonadUtils
import Control.Monad
import Data.Data
+import Data.Semigroup
import Data.Maybe( mapMaybe )
import Data.List ( partition, mapAccumL )
import qualified Data.Foldable as Foldable
@@ -46,6 +47,13 @@ data Bag a
| TwoBags (Bag a) (Bag a) -- INVARIANT: neither branch is empty
| ListBag [a] -- INVARIANT: the list is non-empty
+instance Semigroup (Bag a) where
+ (<>) = unionBags
+
+instance Monoid (Bag a) where
+ mappend = (Data.Semigroup.<>)
+ mempty = emptyBag
+
emptyBag :: Bag a
emptyBag = EmptyBag
diff --git a/compiler/utils/UniqDFM.hs b/compiler/utils/UniqDFM.hs
index bd530b76c3..a682854954 100644
--- a/compiler/utils/UniqDFM.hs
+++ b/compiler/utils/UniqDFM.hs
@@ -57,6 +57,7 @@ module UniqDFM (
udfmToList,
udfmToUfm,
nonDetFoldUDFM,
+ nonDetStrictFoldUDFM,
alwaysUnsafeUfmToUdfm,
) where
@@ -271,6 +272,9 @@ foldUDFM k z m = foldr k z (eltsUDFM m)
nonDetFoldUDFM :: (elt -> a -> a) -> a -> UniqDFM elt -> a
nonDetFoldUDFM k z (UDFM m _i) = foldr k z $ map taggedFst $ M.elems m
+nonDetStrictFoldUDFM :: (elt -> a -> a) -> a -> UniqDFM elt -> a
+nonDetStrictFoldUDFM k z (UDFM m _i) = foldl' (flip k) z $ map taggedFst $ M.elems m
+
eltsUDFM :: UniqDFM elt -> [elt]
eltsUDFM (UDFM m _i) =
map taggedFst $ sortBy (compare `on` taggedSnd) $ M.elems m
diff --git a/compiler/utils/UniqFM.hs b/compiler/utils/UniqFM.hs
index 804d7d19d5..9a7082ade3 100644
--- a/compiler/utils/UniqFM.hs
+++ b/compiler/utils/UniqFM.hs
@@ -56,6 +56,7 @@ module UniqFM (
disjointUFM,
equalKeysUFM,
nonDetFoldUFM, foldUFM, nonDetFoldUFM_Directly,
+ nonDetStrictFoldUFM, nonDetStrictFoldUFM_Directly,
anyUFM, allUFM, seqEltsUFM,
mapUFM, mapUFM_Directly,
elemUFM, elemUFM_Directly,
@@ -331,6 +332,20 @@ nonDetFoldUFM_Directly k z (UFM m) = M.foldrWithKey (k . getUnique) z m
-- See Note [Deterministic UniqFM] to learn about nondeterminism.
-- If you use this please provide a justification why it doesn't introduce
-- nondeterminism.
+nonDetStrictFoldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
+nonDetStrictFoldUFM k z (UFM m) = M.foldl' (flip k) z m
+{-# INLINE nonDetStrictFoldUFM #-}
+
+-- See Note [Deterministic UniqFM] to learn about nondeterminism.
+-- If you use this please provide a justification why it doesn't introduce
+-- nondeterminism.
+nonDetStrictFoldUFM_Directly:: (Unique -> elt -> a -> a) -> a -> UniqFM elt -> a
+nonDetStrictFoldUFM_Directly k z (UFM m) = M.foldlWithKey' (\z' i x -> k (getUnique i) x z') z m
+{-# INLINE nonDetStrictFoldUFM_Directly #-}
+
+-- See Note [Deterministic UniqFM] to learn about nondeterminism.
+-- If you use this please provide a justification why it doesn't introduce
+-- nondeterminism.
nonDetUFMToList :: UniqFM elt -> [(Unique, elt)]
nonDetUFMToList (UFM m) = map (\(k, v) -> (getUnique k, v)) $ M.toList m
diff --git a/testsuite/tests/ghci/scripts/T12550.stdout b/testsuite/tests/ghci/scripts/T12550.stdout
index c7173fc426..6f615e0b08 100644
--- a/testsuite/tests/ghci/scripts/T12550.stdout
+++ b/testsuite/tests/ghci/scripts/T12550.stdout
@@ -21,22 +21,15 @@ class Functor (f ∷ ★ → ★) where
(<$) ∷ ∀ a b. a → f b → f a
{-# MINIMAL fmap #-}
-- Defined in ‘GHC.Base’
-instance Functor V1 -- Defined in ‘GHC.Generics’
-instance Functor (URec Char) -- Defined in ‘GHC.Generics’
-instance Functor (URec Double) -- Defined in ‘GHC.Generics’
-instance Functor (URec Float) -- Defined in ‘GHC.Generics’
-instance Functor (URec Int) -- Defined in ‘GHC.Generics’
-instance Functor (URec Word) -- Defined in ‘GHC.Generics’
-instance Functor U1 -- Defined in ‘GHC.Generics’
-instance ∀ (f ∷ ★ → ★). Functor f ⇒ Functor (Rec1 f)
- -- Defined in ‘GHC.Generics’
-instance Functor Par1 -- Defined in ‘GHC.Generics’
-instance ∀ i (c ∷ Meta) (f ∷ ★ → ★). Functor f ⇒ Functor (M1 i c f)
- -- Defined in ‘GHC.Generics’
-instance ∀ i c. Functor (K1 i c) -- Defined in ‘GHC.Generics’
+instance ∀ a. Functor ((,) a) -- Defined in ‘GHC.Base’
+instance ∀ r. Functor ((->) r) -- Defined in ‘GHC.Base’
+instance Functor IO -- Defined in ‘GHC.Base’
+instance Functor Maybe -- Defined in ‘GHC.Base’
+instance Functor [] -- Defined in ‘GHC.Base’
+instance ∀ a. Functor (Either a) -- Defined in ‘Data.Either’
instance ∀ (f ∷ ★ → ★) (g ∷ ★ → ★).
(Functor f, Functor g) ⇒
- Functor (f :.: g)
+ Functor (f :*: g)
-- Defined in ‘GHC.Generics’
instance ∀ (f ∷ ★ → ★) (g ∷ ★ → ★).
(Functor f, Functor g) ⇒
@@ -44,14 +37,21 @@ instance ∀ (f ∷ ★ → ★) (g ∷ ★ → ★).
-- Defined in ‘GHC.Generics’
instance ∀ (f ∷ ★ → ★) (g ∷ ★ → ★).
(Functor f, Functor g) ⇒
- Functor (f :*: g)
+ Functor (f :.: g)
-- Defined in ‘GHC.Generics’
-instance ∀ a. Functor (Either a) -- Defined in ‘Data.Either’
-instance Functor [] -- Defined in ‘GHC.Base’
-instance Functor Maybe -- Defined in ‘GHC.Base’
-instance Functor IO -- Defined in ‘GHC.Base’
-instance ∀ r. Functor ((->) r) -- Defined in ‘GHC.Base’
-instance ∀ a. Functor ((,) a) -- Defined in ‘GHC.Base’
+instance ∀ i c. Functor (K1 i c) -- Defined in ‘GHC.Generics’
+instance ∀ i (c ∷ Meta) (f ∷ ★ → ★). Functor f ⇒ Functor (M1 i c f)
+ -- Defined in ‘GHC.Generics’
+instance Functor Par1 -- Defined in ‘GHC.Generics’
+instance ∀ (f ∷ ★ → ★). Functor f ⇒ Functor (Rec1 f)
+ -- Defined in ‘GHC.Generics’
+instance Functor U1 -- Defined in ‘GHC.Generics’
+instance Functor (URec Char) -- Defined in ‘GHC.Generics’
+instance Functor (URec Double) -- Defined in ‘GHC.Generics’
+instance Functor (URec Float) -- Defined in ‘GHC.Generics’
+instance Functor (URec Int) -- Defined in ‘GHC.Generics’
+instance Functor (URec Word) -- Defined in ‘GHC.Generics’
+instance Functor V1 -- Defined in ‘GHC.Generics’
datatypeName
∷ ∀ {d} {t ∷ ★ → (★ → ★) → ★ → ★} {f ∷ ★ → ★} {a}.
Datatype d ⇒
diff --git a/testsuite/tests/ghci/scripts/T4175.stdout b/testsuite/tests/ghci/scripts/T4175.stdout
index 9dfcd6c0d6..e06290886b 100644
--- a/testsuite/tests/ghci/scripts/T4175.stdout
+++ b/testsuite/tests/ghci/scripts/T4175.stdout
@@ -1,59 +1,59 @@
type family A a b :: * -- Defined at T4175.hs:7:1
-type instance A (Maybe a) a = a -- Defined at T4175.hs:9:15
-type instance A Int Int = () -- Defined at T4175.hs:8:15
type instance A (B a) b = () -- Defined at T4175.hs:10:15
+type instance A Int Int = () -- Defined at T4175.hs:8:15
+type instance A (Maybe a) a = a -- Defined at T4175.hs:9:15
data family B a -- Defined at T4175.hs:12:1
instance [safe] G B -- Defined at T4175.hs:34:10
-type instance A (B a) b = () -- Defined at T4175.hs:10:15
data instance B () = MkB -- Defined at T4175.hs:13:15
+type instance A (B a) b = () -- Defined at T4175.hs:10:15
class C a where
type family D a b :: *
-- Defined at T4175.hs:16:5
-type instance D () () = Bool -- Defined at T4175.hs:22:10
type instance D Int () = String -- Defined at T4175.hs:19:10
+type instance D () () = Bool -- Defined at T4175.hs:22:10
type family E a :: * where
E () = Bool
E Int = String
-- Defined at T4175.hs:24:1
data () = () -- Defined in ‘GHC.Tuple’
instance [safe] C () -- Defined at T4175.hs:21:10
-instance Eq () -- Defined in ‘GHC.Classes’
instance Monoid () -- Defined in ‘GHC.Base’
-instance Ord () -- Defined in ‘GHC.Classes’
instance Semigroup () -- Defined in ‘GHC.Base’
+instance Bounded () -- Defined in ‘GHC.Enum’
instance Enum () -- Defined in ‘GHC.Enum’
-instance Show () -- Defined in ‘GHC.Show’
+instance Eq () -- Defined in ‘GHC.Classes’
+instance Ord () -- Defined in ‘GHC.Classes’
instance Read () -- Defined in ‘GHC.Read’
-instance Bounded () -- Defined in ‘GHC.Enum’
-type instance D () () = Bool -- Defined at T4175.hs:22:10
+instance Show () -- Defined in ‘GHC.Show’
type instance D Int () = String -- Defined at T4175.hs:19:10
+type instance D () () = Bool -- Defined at T4175.hs:22:10
data instance B () = MkB -- Defined at T4175.hs:13:15
data Maybe a = Nothing | Just a -- Defined in ‘GHC.Maybe’
+instance Traversable Maybe -- Defined in ‘Data.Traversable’
+instance Foldable Maybe -- Defined in ‘Data.Foldable’
instance Applicative Maybe -- Defined in ‘GHC.Base’
-instance Eq a => Eq (Maybe a) -- Defined in ‘GHC.Maybe’
instance Functor Maybe -- Defined in ‘GHC.Base’
+instance MonadFail Maybe -- Defined in ‘Control.Monad.Fail’
instance Monad Maybe -- Defined in ‘GHC.Base’
instance Semigroup a => Monoid (Maybe a) -- Defined in ‘GHC.Base’
-instance Ord a => Ord (Maybe a) -- Defined in ‘GHC.Maybe’
instance Semigroup a => Semigroup (Maybe a)
-- Defined in ‘GHC.Base’
-instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
-instance MonadFail Maybe -- Defined in ‘Control.Monad.Fail’
+instance Eq a => Eq (Maybe a) -- Defined in ‘GHC.Maybe’
+instance Ord a => Ord (Maybe a) -- Defined in ‘GHC.Maybe’
instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’
-instance Foldable Maybe -- Defined in ‘Data.Foldable’
-instance Traversable Maybe -- Defined in ‘Data.Traversable’
+instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
type instance A (Maybe a) a = a -- Defined at T4175.hs:9:15
data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in ‘GHC.Types’
instance [safe] C Int -- Defined at T4175.hs:18:10
-instance Eq Int -- Defined in ‘GHC.Classes’
-instance Ord Int -- Defined in ‘GHC.Classes’
-instance Enum Int -- Defined in ‘GHC.Enum’
+instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Real Int -- Defined in ‘GHC.Real’
-instance Show Int -- Defined in ‘GHC.Show’
-instance Read Int -- Defined in ‘GHC.Read’
instance Bounded Int -- Defined in ‘GHC.Enum’
-instance Integral Int -- Defined in ‘GHC.Real’
+instance Enum Int -- Defined in ‘GHC.Enum’
+instance Eq Int -- Defined in ‘GHC.Classes’
+instance Ord Int -- Defined in ‘GHC.Classes’
+instance Read Int -- Defined in ‘GHC.Read’
+instance Show Int -- Defined in ‘GHC.Show’
type instance D Int () = String -- Defined at T4175.hs:19:10
type instance A Int Int = () -- Defined at T4175.hs:8:15
class Z a -- Defined at T4175.hs:28:1
diff --git a/testsuite/tests/ghci/scripts/T7627.stdout b/testsuite/tests/ghci/scripts/T7627.stdout
index a20f4896b0..a50f2af8cb 100644
--- a/testsuite/tests/ghci/scripts/T7627.stdout
+++ b/testsuite/tests/ghci/scripts/T7627.stdout
@@ -1,12 +1,12 @@
data () = () -- Defined in ‘GHC.Tuple’
-instance Eq () -- Defined in ‘GHC.Classes’
instance Monoid () -- Defined in ‘GHC.Base’
-instance Ord () -- Defined in ‘GHC.Classes’
instance Semigroup () -- Defined in ‘GHC.Base’
+instance Bounded () -- Defined in ‘GHC.Enum’
+instance Read () -- Defined in ‘GHC.Read’
instance Enum () -- Defined in ‘GHC.Enum’
instance Show () -- Defined in ‘GHC.Show’
-instance Read () -- Defined in ‘GHC.Read’
-instance Bounded () -- Defined in ‘GHC.Enum’
+instance Eq () -- Defined in ‘GHC.Classes’
+instance Ord () -- Defined in ‘GHC.Classes’
data (##) :: TYPE ('GHC.Types.TupleRep '[]) = (##)
-- Defined in ‘GHC.Prim’
() :: ()
@@ -14,21 +14,21 @@ data (##) :: TYPE ('GHC.Types.TupleRep '[]) = (##)
( ) :: ()
(# #) :: (# #)
data (,) a b = (,) a b -- Defined in ‘GHC.Tuple’
-instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’
-instance (Eq a, Eq b) => Eq (a, b) -- Defined in ‘GHC.Classes’
-instance Functor ((,) a) -- Defined in ‘GHC.Base’
-instance Monoid a => Monad ((,) a) -- Defined in ‘GHC.Base’
+instance Traversable ((,) a) -- Defined in ‘Data.Traversable’
instance (Monoid a, Monoid b) => Monoid (a, b)
-- Defined in ‘GHC.Base’
-instance (Ord a, Ord b) => Ord (a, b) -- Defined in ‘GHC.Classes’
instance (Semigroup a, Semigroup b) => Semigroup (a, b)
-- Defined in ‘GHC.Base’
-instance (Show a, Show b) => Show (a, b) -- Defined in ‘GHC.Show’
-instance (Read a, Read b) => Read (a, b) -- Defined in ‘GHC.Read’
instance Foldable ((,) a) -- Defined in ‘Data.Foldable’
-instance Traversable ((,) a) -- Defined in ‘Data.Traversable’
instance (Bounded a, Bounded b) => Bounded (a, b)
-- Defined in ‘GHC.Enum’
+instance (Eq a, Eq b) => Eq (a, b) -- Defined in ‘GHC.Classes’
+instance (Ord a, Ord b) => Ord (a, b) -- Defined in ‘GHC.Classes’
+instance (Read a, Read b) => Read (a, b) -- Defined in ‘GHC.Read’
+instance (Show a, Show b) => Show (a, b) -- Defined in ‘GHC.Show’
+instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’
+instance Functor ((,) a) -- Defined in ‘GHC.Base’
+instance Monoid a => Monad ((,) a) -- Defined in ‘GHC.Base’
data (#,#) (a :: TYPE k0) (b :: TYPE k1) :: TYPE
('GHC.Types.TupleRep '[k0, k1])
= (#,#) a b
diff --git a/testsuite/tests/ghci/scripts/T8469.stdout b/testsuite/tests/ghci/scripts/T8469.stdout
index 1a511e6b55..0bbaaedfbe 100644
--- a/testsuite/tests/ghci/scripts/T8469.stdout
+++ b/testsuite/tests/ghci/scripts/T8469.stdout
@@ -1,10 +1,10 @@
data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in ‘GHC.Types’
-instance Eq Int -- Defined in ‘GHC.Classes’
-instance Ord Int -- Defined in ‘GHC.Classes’
+instance Bounded Int -- Defined in ‘GHC.Enum’
+instance Read Int -- Defined in ‘GHC.Read’
instance Enum Int -- Defined in ‘GHC.Enum’
+instance Integral Int -- Defined in ‘GHC.Real’
instance Num Int -- Defined in ‘GHC.Num’
instance Real Int -- Defined in ‘GHC.Real’
instance Show Int -- Defined in ‘GHC.Show’
-instance Read Int -- Defined in ‘GHC.Read’
-instance Bounded Int -- Defined in ‘GHC.Enum’
-instance Integral Int -- Defined in ‘GHC.Real’
+instance Eq Int -- Defined in ‘GHC.Classes’
+instance Ord Int -- Defined in ‘GHC.Classes’
diff --git a/testsuite/tests/ghci/scripts/T8535.stdout b/testsuite/tests/ghci/scripts/T8535.stdout
index a0a5730d2b..d1d430a2fb 100644
--- a/testsuite/tests/ghci/scripts/T8535.stdout
+++ b/testsuite/tests/ghci/scripts/T8535.stdout
@@ -1,7 +1,7 @@
data (->) (a :: TYPE q) (b :: TYPE r) -- Defined in ‘GHC.Prim’
infixr -1 ->
+instance Monoid b => Monoid (a -> b) -- Defined in ‘GHC.Base’
+instance Semigroup b => Semigroup (a -> b) -- Defined in ‘GHC.Base’
instance Applicative ((->) a) -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
-instance Monoid b => Monoid (a -> b) -- Defined in ‘GHC.Base’
-instance Semigroup b => Semigroup (a -> b) -- Defined in ‘GHC.Base’
diff --git a/testsuite/tests/ghci/scripts/T8674.stdout b/testsuite/tests/ghci/scripts/T8674.stdout
index d938f95692..4b1bca366d 100644
--- a/testsuite/tests/ghci/scripts/T8674.stdout
+++ b/testsuite/tests/ghci/scripts/T8674.stdout
@@ -1,4 +1,4 @@
data family Sing (a :: k) -- Defined at T8674.hs:4:1
-data instance Sing Bool = SBool -- Defined at T8674.hs:6:15
data instance forall k (a :: [k]). Sing a = SNil
-- Defined at T8674.hs:5:15
+data instance Sing Bool = SBool -- Defined at T8674.hs:6:15
diff --git a/testsuite/tests/ghci/scripts/T9881.stdout b/testsuite/tests/ghci/scripts/T9881.stdout
index 68acea7c61..ea81ed1dcb 100644
--- a/testsuite/tests/ghci/scripts/T9881.stdout
+++ b/testsuite/tests/ghci/scripts/T9881.stdout
@@ -3,17 +3,17 @@ data Data.ByteString.Lazy.ByteString
| Data.ByteString.Lazy.Internal.Chunk {-# UNPACK #-}Data.ByteString.ByteString
Data.ByteString.Lazy.ByteString
-- Defined in ‘Data.ByteString.Lazy.Internal’
-instance Eq Data.ByteString.Lazy.ByteString
- -- Defined in ‘Data.ByteString.Lazy.Internal’
instance Monoid Data.ByteString.Lazy.ByteString
-- Defined in ‘Data.ByteString.Lazy.Internal’
-instance Ord Data.ByteString.Lazy.ByteString
+instance Read Data.ByteString.Lazy.ByteString
-- Defined in ‘Data.ByteString.Lazy.Internal’
instance Semigroup Data.ByteString.Lazy.ByteString
-- Defined in ‘Data.ByteString.Lazy.Internal’
instance Show Data.ByteString.Lazy.ByteString
-- Defined in ‘Data.ByteString.Lazy.Internal’
-instance Read Data.ByteString.Lazy.ByteString
+instance Eq Data.ByteString.Lazy.ByteString
+ -- Defined in ‘Data.ByteString.Lazy.Internal’
+instance Ord Data.ByteString.Lazy.ByteString
-- Defined in ‘Data.ByteString.Lazy.Internal’
data Data.ByteString.ByteString
@@ -22,15 +22,15 @@ data Data.ByteString.ByteString
{-# UNPACK #-}Int
{-# UNPACK #-}Int
-- Defined in ‘Data.ByteString.Internal’
-instance Eq Data.ByteString.ByteString
- -- Defined in ‘Data.ByteString.Internal’
instance Monoid Data.ByteString.ByteString
-- Defined in ‘Data.ByteString.Internal’
-instance Ord Data.ByteString.ByteString
+instance Read Data.ByteString.ByteString
-- Defined in ‘Data.ByteString.Internal’
instance Semigroup Data.ByteString.ByteString
-- Defined in ‘Data.ByteString.Internal’
instance Show Data.ByteString.ByteString
-- Defined in ‘Data.ByteString.Internal’
-instance Read Data.ByteString.ByteString
+instance Eq Data.ByteString.ByteString
+ -- Defined in ‘Data.ByteString.Internal’
+instance Ord Data.ByteString.ByteString
-- Defined in ‘Data.ByteString.Internal’
diff --git a/testsuite/tests/ghci/scripts/ghci008.stdout b/testsuite/tests/ghci/scripts/ghci008.stdout
index abed6d21f3..7e31fb3e51 100644
--- a/testsuite/tests/ghci/scripts/ghci008.stdout
+++ b/testsuite/tests/ghci/scripts/ghci008.stdout
@@ -33,7 +33,7 @@ class (RealFrac a, Floating a) => RealFloat a where
encodeFloat, isNaN, isInfinite, isDenormalized, isNegativeZero,
isIEEE #-}
-- Defined in ‘GHC.Float’
-instance RealFloat Float -- Defined in ‘GHC.Float’
instance RealFloat Double -- Defined in ‘GHC.Float’
+instance RealFloat Float -- Defined in ‘GHC.Float’
base-4.13.0.0:Data.OldList.isPrefixOf :: Eq a => [a] -> [a] -> Bool
-- Defined in ‘base-4.13.0.0:Data.OldList’
diff --git a/testsuite/tests/ghci/scripts/ghci011.stdout b/testsuite/tests/ghci/scripts/ghci011.stdout
index 6dd5782d6c..0e5ddc3259 100644
--- a/testsuite/tests/ghci/scripts/ghci011.stdout
+++ b/testsuite/tests/ghci/scripts/ghci011.stdout
@@ -1,38 +1,38 @@
data [] a = [] | a : [a] -- Defined in ‘GHC.Types’
-instance Applicative [] -- Defined in ‘GHC.Base’
-instance Eq a => Eq [a] -- Defined in ‘GHC.Classes’
-instance Functor [] -- Defined in ‘GHC.Base’
-instance Monad [] -- Defined in ‘GHC.Base’
instance Monoid [a] -- Defined in ‘GHC.Base’
-instance Ord a => Ord [a] -- Defined in ‘GHC.Classes’
instance Semigroup [a] -- Defined in ‘GHC.Base’
-instance Show a => Show [a] -- Defined in ‘GHC.Show’
-instance MonadFail [] -- Defined in ‘Control.Monad.Fail’
-instance Read a => Read [a] -- Defined in ‘GHC.Read’
instance Foldable [] -- Defined in ‘Data.Foldable’
instance Traversable [] -- Defined in ‘Data.Traversable’
+instance Read a => Read [a] -- Defined in ‘GHC.Read’
+instance Show a => Show [a] -- Defined in ‘GHC.Show’
+instance Applicative [] -- Defined in ‘GHC.Base’
+instance Functor [] -- Defined in ‘GHC.Base’
+instance MonadFail [] -- Defined in ‘Control.Monad.Fail’
+instance Monad [] -- Defined in ‘GHC.Base’
+instance Eq a => Eq [a] -- Defined in ‘GHC.Classes’
+instance Ord a => Ord [a] -- Defined in ‘GHC.Classes’
data () = () -- Defined in ‘GHC.Tuple’
-instance Eq () -- Defined in ‘GHC.Classes’
instance Monoid () -- Defined in ‘GHC.Base’
-instance Ord () -- Defined in ‘GHC.Classes’
instance Semigroup () -- Defined in ‘GHC.Base’
-instance Enum () -- Defined in ‘GHC.Enum’
-instance Show () -- Defined in ‘GHC.Show’
instance Read () -- Defined in ‘GHC.Read’
instance Bounded () -- Defined in ‘GHC.Enum’
+instance Enum () -- Defined in ‘GHC.Enum’
+instance Ord () -- Defined in ‘GHC.Classes’
+instance Show () -- Defined in ‘GHC.Show’
+instance Eq () -- Defined in ‘GHC.Classes’
data (,) a b = (,) a b -- Defined in ‘GHC.Tuple’
-instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’
-instance (Eq a, Eq b) => Eq (a, b) -- Defined in ‘GHC.Classes’
-instance Functor ((,) a) -- Defined in ‘GHC.Base’
-instance Monoid a => Monad ((,) a) -- Defined in ‘GHC.Base’
+instance Traversable ((,) a) -- Defined in ‘Data.Traversable’
instance (Monoid a, Monoid b) => Monoid (a, b)
-- Defined in ‘GHC.Base’
-instance (Ord a, Ord b) => Ord (a, b) -- Defined in ‘GHC.Classes’
instance (Semigroup a, Semigroup b) => Semigroup (a, b)
-- Defined in ‘GHC.Base’
-instance (Show a, Show b) => Show (a, b) -- Defined in ‘GHC.Show’
-instance (Read a, Read b) => Read (a, b) -- Defined in ‘GHC.Read’
instance Foldable ((,) a) -- Defined in ‘Data.Foldable’
-instance Traversable ((,) a) -- Defined in ‘Data.Traversable’
instance (Bounded a, Bounded b) => Bounded (a, b)
-- Defined in ‘GHC.Enum’
+instance (Eq a, Eq b) => Eq (a, b) -- Defined in ‘GHC.Classes’
+instance (Ord a, Ord b) => Ord (a, b) -- Defined in ‘GHC.Classes’
+instance (Read a, Read b) => Read (a, b) -- Defined in ‘GHC.Read’
+instance (Show a, Show b) => Show (a, b) -- Defined in ‘GHC.Show’
+instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’
+instance Functor ((,) a) -- Defined in ‘GHC.Base’
+instance Monoid a => Monad ((,) a) -- Defined in ‘GHC.Base’
diff --git a/testsuite/tests/ghci/scripts/ghci020.stdout b/testsuite/tests/ghci/scripts/ghci020.stdout
index a0a5730d2b..d1d430a2fb 100644
--- a/testsuite/tests/ghci/scripts/ghci020.stdout
+++ b/testsuite/tests/ghci/scripts/ghci020.stdout
@@ -1,7 +1,7 @@
data (->) (a :: TYPE q) (b :: TYPE r) -- Defined in ‘GHC.Prim’
infixr -1 ->
+instance Monoid b => Monoid (a -> b) -- Defined in ‘GHC.Base’
+instance Semigroup b => Semigroup (a -> b) -- Defined in ‘GHC.Base’
instance Applicative ((->) a) -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
-instance Monoid b => Monoid (a -> b) -- Defined in ‘GHC.Base’
-instance Semigroup b => Semigroup (a -> b) -- Defined in ‘GHC.Base’
diff --git a/testsuite/tests/ghci/scripts/ghci064.stdout b/testsuite/tests/ghci/scripts/ghci064.stdout
new file mode 100644
index 0000000000..ad2d135b80
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/ghci064.stdout
@@ -0,0 +1,49 @@
+instance Foldable Maybe -- Defined in ‘Data.Foldable’
+instance Traversable Maybe -- Defined in ‘Data.Traversable’
+instance GHC.Base.Alternative Maybe -- Defined in ‘GHC.Base’
+instance Applicative Maybe -- Defined in ‘GHC.Base’
+instance Functor Maybe -- Defined in ‘GHC.Base’
+instance MonadFail Maybe -- Defined in ‘Control.Monad.Fail’
+instance GHC.Base.MonadPlus Maybe -- Defined in ‘GHC.Base’
+instance Monad Maybe -- Defined in ‘GHC.Base’
+instance GHC.Generics.SingKind w => GHC.Generics.SingKind (Maybe w)
+ -- Defined in ‘GHC.Generics’
+instance Semigroup w => Monoid (Maybe w) -- Defined in ‘GHC.Base’
+instance Semigroup w => Semigroup (Maybe w)
+ -- Defined in ‘GHC.Base’
+instance GHC.Generics.Generic (Maybe w)
+ -- Defined in ‘GHC.Generics’
+instance Read w => Read (Maybe w) -- Defined in ‘GHC.Read’
+instance Ord w => Ord (Maybe w) -- Defined in ‘GHC.Maybe’
+instance Show w => Show (Maybe w) -- Defined in ‘GHC.Show’
+instance Eq w => Eq (Maybe w) -- Defined in ‘GHC.Maybe’
+instance Monoid [w] -- Defined in ‘GHC.Base’
+instance Semigroup [w] -- Defined in ‘GHC.Base’
+instance Read w => Read [w] -- Defined in ‘GHC.Read’
+instance GHC.Generics.Generic [w] -- Defined in ‘GHC.Generics’
+instance Eq w => Eq [w] -- Defined in ‘GHC.Classes’
+instance Ord w => Ord [w] -- Defined in ‘GHC.Classes’
+instance Show w => Show [w] -- Defined in ‘GHC.Show’
+instance [safe] MyShow w => MyShow [w]
+ -- Defined at ghci064.hs:8:10
+instance GHC.Generics.Generic [T] -- Defined in ‘GHC.Generics’
+instance Monoid [T] -- Defined in ‘GHC.Base’
+instance Semigroup [T] -- Defined in ‘GHC.Base’
+instance [safe] MyShow [T] -- Defined at ghci064.hs:16:10
+instance [safe] MyShow [T] -- Defined at ghci064.hs:8:10
+instance GHC.Generics.SingKind Bool -- Defined in ‘GHC.Generics’
+instance Foreign.Storable.Storable Bool
+ -- Defined in ‘Foreign.Storable’
+instance GHC.Generics.Generic Bool -- Defined in ‘GHC.Generics’
+instance GHC.Bits.Bits Bool -- Defined in ‘GHC.Bits’
+instance GHC.Bits.FiniteBits Bool -- Defined in ‘GHC.Bits’
+instance GHC.Ix.Ix Bool -- Defined in ‘GHC.Ix’
+instance Bounded Bool -- Defined in ‘GHC.Enum’
+instance Enum Bool -- Defined in ‘GHC.Enum’
+instance Eq Bool -- Defined in ‘GHC.Classes’
+instance Ord Bool -- Defined in ‘GHC.Classes’
+instance Read Bool -- Defined in ‘GHC.Read’
+instance Show Bool -- Defined in ‘GHC.Show’
+instance Traversable ((,) Int) -- Defined in ‘Data.Traversable’
+instance Foldable ((,) Int) -- Defined in ‘Data.Foldable’
+instance Functor ((,) Int) -- Defined in ‘GHC.Base’
diff --git a/testsuite/tests/ghci/should_run/T10145.stdout b/testsuite/tests/ghci/should_run/T10145.stdout
index a0a5730d2b..d1d430a2fb 100644
--- a/testsuite/tests/ghci/should_run/T10145.stdout
+++ b/testsuite/tests/ghci/should_run/T10145.stdout
@@ -1,7 +1,7 @@
data (->) (a :: TYPE q) (b :: TYPE r) -- Defined in ‘GHC.Prim’
infixr -1 ->
+instance Monoid b => Monoid (a -> b) -- Defined in ‘GHC.Base’
+instance Semigroup b => Semigroup (a -> b) -- Defined in ‘GHC.Base’
instance Applicative ((->) a) -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
-instance Monoid b => Monoid (a -> b) -- Defined in ‘GHC.Base’
-instance Semigroup b => Semigroup (a -> b) -- Defined in ‘GHC.Base’
diff --git a/testsuite/tests/ghci/should_run/T18594.stdout b/testsuite/tests/ghci/should_run/T18594.stdout
new file mode 100644
index 0000000000..1c6c93ad7a
--- /dev/null
+++ b/testsuite/tests/ghci/should_run/T18594.stdout
@@ -0,0 +1,15 @@
+type (->) :: * -> * -> *
+type (->) = FUN 'Many :: * -> * -> *
+ -- Defined in ‘GHC.Types’
+infixr -1 ->
+instance Monoid b => Monoid (a -> b) -- Defined in ‘GHC.Base’
+instance Semigroup b => Semigroup (a -> b) -- Defined in ‘GHC.Base’
+instance Applicative ((->) r) -- Defined in ‘GHC.Base’
+instance Functor ((->) r) -- Defined in ‘GHC.Base’
+instance Monad ((->) r) -- Defined in ‘GHC.Base’
+type Type :: *
+type Type = TYPE LiftedRep
+ -- Defined in ‘GHC.Types’
+type Type :: Type
+type Type = TYPE LiftedRep
+ -- Defined in ‘GHC.Types’
diff --git a/testsuite/tests/perf/compiler/T19703/Makefile b/testsuite/tests/perf/compiler/T19703/Makefile
index cbc0883748..40f509351b 100644
--- a/testsuite/tests/perf/compiler/T19703/Makefile
+++ b/testsuite/tests/perf/compiler/T19703/Makefile
@@ -1,4 +1,4 @@
-TOP=/opt/exp/ghc/ghc-T19703/testsuite
+TOP=../../../../testsuite
include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/test.mk
@@ -7,4 +7,4 @@ prep-T19703:
"$(PYTHON)" genT19703.py
"$(TEST_HC)" $(TEST_HC_OPTS) Fam.hs
"$(TEST_HC)" $(TEST_HC_OPTS) A.hs
- "$(TEST_HC)" $(TEST_HC_OPTS) B.hs \ No newline at end of file
+ "$(TEST_HC)" $(TEST_HC_OPTS) B.hs
diff --git a/testsuite/tests/perf/compiler/T19703/genT19703.py b/testsuite/tests/perf/compiler/T19703/genT19703.py
index f41ecac639..e805dec2a1 100644
--- a/testsuite/tests/perf/compiler/T19703/genT19703.py
+++ b/testsuite/tests/perf/compiler/T19703/genT19703.py
@@ -22,17 +22,18 @@ def gen_join():
'''))
def gen_instances(mod_name: str, n: int):
- write_file(f'{mod_name}.hs', dedent(f'''
+ out = dedent('''
{{-# LANGUAGE TypeFamilies #-}}
module {mod_name} where
import Fam
- ''') + '\n'.join(
- dedent(f'''
+ '''.format(mod_name=mod_name))
+ out += '\n'.join(
+ dedent('''
data T{i} = T{i}
type instance Fam T{i} = Int
- ''')
- for i in range(n)
- ))
+ ''').format(i=str(i))
+ for i in range(n))
+ write_file('{}.hs'.format(mod_name), out)
gen_fam()
gen_instances('A', n=5000)
diff --git a/testsuite/tests/showIface/Orphans.stdout b/testsuite/tests/showIface/Orphans.stdout
index 38e4066d9e..99910c975c 100644
--- a/testsuite/tests/showIface/Orphans.stdout
+++ b/testsuite/tests/showIface/Orphans.stdout
@@ -1,5 +1,5 @@
-instance [orphan] GHC.Exts.IsList [GHC.Types.Bool] = $fIsListBool
-instance GHC.Exts.IsList [X] = $fIsListX
+instance [orphan] GHC.Exts.IsList [GHC.Exts.IsList, GHC.Types.Bool]
+instance GHC.Exts.IsList [GHC.Exts.IsList, X] = $fIsListX
family instance GHC.Exts.Item [X] = D:R:ItemX
family instance [orphan] GHC.Exts.Item [GHC.Types.Bool]
"myrule1" [orphan] forall @ a.
diff --git a/testsuite/tests/th/T17296.stderr b/testsuite/tests/th/T17296.stderr
index 4a6f1ac3bd..f103f7986a 100644
--- a/testsuite/tests/th/T17296.stderr
+++ b/testsuite/tests/th/T17296.stderr
@@ -1,19 +1,19 @@
data family T17296.Foo1 :: * -> *
-data instance T17296.Foo1 GHC.Types.Bool = T17296.Foo1Bool
data instance forall (a_0 :: *). T17296.Foo1 (GHC.Maybe.Maybe a_0)
+data instance T17296.Foo1 GHC.Types.Bool = T17296.Foo1Bool
data family T17296.Foo2 :: k_0 -> *
-data instance T17296.Foo2 GHC.Types.Bool = T17296.Foo2Bool
-data instance forall (a_1 :: *). T17296.Foo2 (GHC.Maybe.Maybe a_1 :: *)
-data instance T17296.Foo2 :: GHC.Types.Char -> *
data instance T17296.Foo2 :: (GHC.Types.Char -> GHC.Types.Char) ->
*
+data instance T17296.Foo2 :: GHC.Types.Char -> *
+data instance forall (a_1 :: *). T17296.Foo2 (GHC.Maybe.Maybe a_1 :: *)
+data instance T17296.Foo2 GHC.Types.Bool = T17296.Foo2Bool
data family T17296.Foo3 :: k_0
-data instance T17296.Foo3 :: *
-data instance T17296.Foo3 GHC.Types.Bool = T17296.Foo3Bool
-data instance forall (a_1 :: *). T17296.Foo3 (GHC.Maybe.Maybe a_1 :: *)
data instance T17296.Foo3 :: GHC.Types.Char -> *
data instance T17296.Foo3 :: (GHC.Types.Char -> GHC.Types.Char) ->
*
+data instance forall (a_1 :: *). T17296.Foo3 (GHC.Maybe.Maybe a_1 :: *)
+data instance T17296.Foo3 GHC.Types.Bool = T17296.Foo3Bool
+data instance T17296.Foo3 :: *
diff --git a/testsuite/tests/th/T1835.stdout b/testsuite/tests/th/T1835.stdout
index 7d34ae01f0..5b21c0352c 100644
--- a/testsuite/tests/th/T1835.stdout
+++ b/testsuite/tests/th/T1835.stdout
@@ -1,8 +1,8 @@
class GHC.Classes.Eq a_0 => Main.MyClass (a_0 :: *)
-instance GHC.Classes.Ord a_1 => Main.MyClass (Main.Quux2 a_1)
-instance GHC.Classes.Eq a_2 => Main.MyClass (Main.Quux a_2)
-instance Main.MyClass Main.Baz
instance Main.MyClass Main.Foo
+instance Main.MyClass Main.Baz
+instance GHC.Classes.Eq a_1 => Main.MyClass (Main.Quux a_1)
+instance GHC.Classes.Ord a_2 => Main.MyClass (Main.Quux2 a_2)
True
True
True
diff --git a/testsuite/tests/th/T8953.stderr b/testsuite/tests/th/T8953.stderr
index d87acef442..ba19e035b9 100644
--- a/testsuite/tests/th/T8953.stderr
+++ b/testsuite/tests/th/T8953.stderr
@@ -1,16 +1,16 @@
type family T8953.Poly (a_0 :: k_1) :: *
-type instance forall (x_2 :: GHC.Types.Bool). T8953.Poly (x_2 :: GHC.Types.Bool) = GHC.Types.Int
-type instance forall (k_3 :: *)
- (x_4 :: GHC.Maybe.Maybe k_3). T8953.Poly (x_4 :: GHC.Maybe.Maybe k_3) = GHC.Types.Double
+type instance forall (k_2 :: *)
+ (x_3 :: GHC.Maybe.Maybe k_2). T8953.Poly (x_3 :: GHC.Maybe.Maybe k_2) = GHC.Types.Double
+type instance forall (x_4 :: GHC.Types.Bool). T8953.Poly (x_4 :: GHC.Types.Bool) = GHC.Types.Int
type family T8953.Silly :: k_0 -> *
-type instance T8953.Silly = (Data.Proxy.Proxy :: * -> *)
type instance T8953.Silly = (Data.Proxy.Proxy :: (* -> *) -> *)
+type instance T8953.Silly = (Data.Proxy.Proxy :: * -> *)
T8953.a :: Data.Proxy.Proxy (Data.Proxy.Proxy :: * -> *)
T8953.b :: Data.Proxy.Proxy (Data.Proxy.Proxy :: (* -> *) -> *)
type T8953.StarProxy (a_0 :: *) = Data.Proxy.Proxy a_0
class T8953.PC (a_0 :: k_1)
-instance T8953.PC (a_2 :: *)
-instance T8953.PC (Data.Proxy.Proxy :: (k_3 -> *) -> *)
+instance T8953.PC (Data.Proxy.Proxy :: (k_2 -> *) -> *)
+instance T8953.PC (a_3 :: *)
type family T8953.F (a_0 :: *) :: k_1
type instance T8953.F GHC.Types.Char = T8953.G (T8953.T1 :: * ->
(* -> *) -> *)
diff --git a/testsuite/tests/th/TH_reifyDecl1.stderr b/testsuite/tests/th/TH_reifyDecl1.stderr
index 5ae01471f3..261dd2cebb 100644
--- a/testsuite/tests/th/TH_reifyDecl1.stderr
+++ b/testsuite/tests/th/TH_reifyDecl1.stderr
@@ -35,8 +35,8 @@ data family TH_reifyDecl1.DF2 (a_0 :: *) :: *
data instance TH_reifyDecl1.DF2 GHC.Types.Bool
= TH_reifyDecl1.DBool
data family TH_reifyDecl1.DF3 (a_0 :: k_1) :: *
-data instance forall (a_2 :: *). TH_reifyDecl1.DF3 (a_2 :: *)
- = TH_reifyDecl1.DF3Bool
-data instance forall (b_3 :: * ->
- *). TH_reifyDecl1.DF3 (b_3 :: * -> *)
+data instance forall (b_2 :: * ->
+ *). TH_reifyDecl1.DF3 (b_2 :: * -> *)
= TH_reifyDecl1.DF3Char
+data instance forall (a_3 :: *). TH_reifyDecl1.DF3 (a_3 :: *)
+ = TH_reifyDecl1.DF3Bool
diff --git a/utils/haddock b/utils/haddock
-Subproject e233b80e3cf8414bdae9574c748e5f89e4c57ad
+Subproject e6ca100973c496cd98da3385594fa9a81320f7c
diff --git a/utils/hsc2hs b/utils/hsc2hs
-Subproject efb556cc2689cae42abadae87d778ae20fbc0a1
+Subproject 24100ea521596922d3edc8370b3d9f7b845ae4c