ghc-lib 0.20220301 → 0.20220401
raw patch · 148 files changed
+4586/−3424 lines, 148 filesdep ~ghc-lib-parser
Dependency ranges changed: ghc-lib-parser
Files
- compiler/GHC.hs +3/−4
- compiler/GHC/Builtin/Names/TH.hs +9/−7
- compiler/GHC/Builtin/Utils.hs +4/−4
- compiler/GHC/ByteCode/InfoTable.hs +0/−2
- compiler/GHC/ByteCode/Instr.hs +1/−1
- compiler/GHC/Cmm/CallConv.hs +0/−1
- compiler/GHC/Cmm/Dataflow.hs +5/−5
- compiler/GHC/Cmm/InitFini.hs +78/−0
- compiler/GHC/Cmm/Parser.y +1/−0
- compiler/GHC/Cmm/Ppr/Decl.hs +2/−0
- compiler/GHC/Cmm/ProcPoint.hs +1/−1
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs +3/−3
- compiler/GHC/CmmToAsm/CFG.hs +3/−3
- compiler/GHC/CmmToAsm/Dwarf.hs +1/−1
- compiler/GHC/CmmToAsm/PPC/CodeGen.hs +7/−5
- compiler/GHC/CmmToAsm/PPC/Ppr.hs +2/−0
- compiler/GHC/CmmToAsm/Ppr.hs +11/−1
- compiler/GHC/CmmToAsm/Reg/Linear.hs +3/−3
- compiler/GHC/CmmToAsm/X86/CodeGen.hs +40/−6
- compiler/GHC/CmmToC.hs +33/−34
- compiler/GHC/CmmToLlvm.hs +1/−1
- compiler/GHC/CmmToLlvm/CodeGen.hs +2/−2
- compiler/GHC/CmmToLlvm/Data.hs +44/−1
- compiler/GHC/Core/Opt/CprAnal.hs +76/−39
- compiler/GHC/Core/Opt/DmdAnal.hs +183/−42
- compiler/GHC/Core/Opt/Exitify.hs +2/−2
- compiler/GHC/Core/Opt/FloatIn.hs +3/−2
- compiler/GHC/Core/Opt/FloatOut.hs +2/−0
- compiler/GHC/Core/Opt/Simplify.hs +36/−17
- compiler/GHC/Core/Opt/Simplify/Env.hs +2/−0
- compiler/GHC/Core/Opt/Simplify/Utils.hs +4/−11
- compiler/GHC/Core/Opt/SpecConstr.hs +26/−14
- compiler/GHC/Core/Opt/Specialise.hs +6/−1
- compiler/GHC/Core/Opt/WorkWrap.hs +29/−15
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs +166/−129
- compiler/GHC/CoreToStg.hs +8/−3
- compiler/GHC/CoreToStg/Prep.hs +7/−15
- compiler/GHC/Data/Graph/Color.hs +6/−6
- compiler/GHC/Driver/Backpack.hs +6/−1
- compiler/GHC/Driver/CodeOutput.hs +49/−34
- compiler/GHC/Driver/Config/StgToCmm.hs +3/−1
- compiler/GHC/Driver/Config/Tidy.hs +73/−0
- compiler/GHC/Driver/Main.hs +58/−11
- compiler/GHC/Driver/Make.hs +31/−67
- compiler/GHC/Hs/Syn/Type.hs +2/−3
- compiler/GHC/HsToCore.hs +2/−4
- compiler/GHC/HsToCore/Binds.hs +12/−9
- compiler/GHC/HsToCore/Coverage.hs +18/−23
- compiler/GHC/HsToCore/Docs.hs +281/−116
- compiler/GHC/HsToCore/Expr.hs +10/−9
- compiler/GHC/HsToCore/Foreign/Decl.hs +21/−19
- compiler/GHC/HsToCore/Match.hs +1/−0
- compiler/GHC/HsToCore/Match/Literal.hs +3/−3
- compiler/GHC/HsToCore/Pmc/Desugar.hs +4/−3
- compiler/GHC/HsToCore/Pmc/Solver.hs +24/−24
- compiler/GHC/HsToCore/Quote.hs +14/−10
- compiler/GHC/HsToCore/Types.hs +1/−1
- compiler/GHC/Iface/Ext/Ast.hs +68/−38
- compiler/GHC/Iface/Load.hs +6/−17
- compiler/GHC/Iface/Make.hs +8/−14
- compiler/GHC/Iface/Recomp.hs +0/−1
- compiler/GHC/Iface/Recomp/Flags.hs +3/−4
- compiler/GHC/Iface/Tidy.hs +137/−170
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs +40/−60
- compiler/GHC/IfaceToCore.hs +2/−1
- compiler/GHC/Linker/Loader.hs +7/−29
- compiler/GHC/Llvm/Ppr.hs +1/−0
- compiler/GHC/Llvm/Types.hs +2/−0
- compiler/GHC/Plugins.hs +8/−0
- compiler/GHC/Rename/Doc.hs +46/−0
- compiler/GHC/Rename/Env.hs +20/−9
- compiler/GHC/Rename/Expr.hs +7/−4
- compiler/GHC/Rename/Expr.hs-boot +6/−0
- compiler/GHC/Rename/HsType.hs +13/−16
- compiler/GHC/Rename/Module.hs +26/−12
- compiler/GHC/Rename/Names.hs +3/−3
- compiler/GHC/Rename/Splice.hs +70/−42
- compiler/GHC/Runtime/Eval.hs +11/−20
- compiler/GHC/Stg/BcPrep.hs +2/−3
- compiler/GHC/Stg/CSE.hs +6/−6
- compiler/GHC/Stg/Debug.hs +2/−1
- compiler/GHC/Stg/FVs.hs +3/−2
- compiler/GHC/Stg/InferTags.hs +16/−5
- compiler/GHC/Stg/InferTags/Rewrite.hs +17/−18
- compiler/GHC/Stg/Lift.hs +4/−2
- compiler/GHC/Stg/Lift/Analysis.hs +2/−2
- compiler/GHC/Stg/Lint.hs +11/−6
- compiler/GHC/Stg/Stats.hs +1/−2
- compiler/GHC/Stg/Unarise.hs +38/−25
- compiler/GHC/Stg/Utils.hs +8/−5
- compiler/GHC/StgToByteCode.hs +17/−16
- compiler/GHC/StgToCmm.hs +4/−7
- compiler/GHC/StgToCmm/Bind.hs +21/−15
- compiler/GHC/StgToCmm/Closure.hs +4/−3
- compiler/GHC/StgToCmm/DataCon.hs +2/−1
- compiler/GHC/StgToCmm/Env.hs +10/−1
- compiler/GHC/StgToCmm/Expr.hs +9/−8
- compiler/GHC/StgToCmm/Expr.hs-boot +0/−7
- compiler/GHC/StgToCmm/Prim.hs +2/−2
- compiler/GHC/StgToCmm/TagCheck.hs +36/−12
- compiler/GHC/StgToCmm/Ticky.hs +116/−28
- compiler/GHC/Tc/Deriv.hs +189/−151
- compiler/GHC/Tc/Deriv/Functor.hs +3/−3
- compiler/GHC/Tc/Deriv/Generate.hs +171/−134
- compiler/GHC/Tc/Deriv/Generics.hs +92/−95
- compiler/GHC/Tc/Deriv/Infer.hs +154/−150
- compiler/GHC/Tc/Deriv/Utils.hs +347/−157
- compiler/GHC/Tc/Errors.hs +47/−28
- compiler/GHC/Tc/Errors/Hole.hs +39/−18
- compiler/GHC/Tc/Gen/App.hs +31/−29
- compiler/GHC/Tc/Gen/Arrow.hs +22/−15
- compiler/GHC/Tc/Gen/Bind.hs +46/−31
- compiler/GHC/Tc/Gen/Export.hs +19/−14
- compiler/GHC/Tc/Gen/Expr.hs +40/−39
- compiler/GHC/Tc/Gen/Expr.hs-boot +4/−3
- compiler/GHC/Tc/Gen/Foreign.hs +80/−108
- compiler/GHC/Tc/Gen/Head.hs +8/−11
- compiler/GHC/Tc/Gen/Match.hs +17/−26
- compiler/GHC/Tc/Gen/Pat.hs +65/−37
- compiler/GHC/Tc/Gen/Rule.hs +18/−22
- compiler/GHC/Tc/Gen/Splice.hs +64/−55
- compiler/GHC/Tc/Gen/Splice.hs-boot +7/−7
- compiler/GHC/Tc/Module.hs +37/−23
- compiler/GHC/Tc/Solver.hs +10/−9
- compiler/GHC/Tc/Solver/Canonical.hs +39/−214
- compiler/GHC/Tc/Solver/Interact.hs +9/−6
- compiler/GHC/Tc/Solver/Monad.hs +38/−101
- compiler/GHC/Tc/TyCl.hs +1/−1
- compiler/GHC/Tc/TyCl/Build.hs +2/−0
- compiler/GHC/Tc/TyCl/Class.hs +3/−4
- compiler/GHC/Tc/TyCl/Instance.hs +12/−16
- compiler/GHC/Tc/TyCl/PatSyn.hs +6/−1
- compiler/GHC/Tc/TyCl/Utils.hs +8/−8
- compiler/GHC/Tc/Utils/Concrete.hs +217/−255
- compiler/GHC/Tc/Utils/Env.hs +1/−1
- compiler/GHC/Tc/Utils/Instantiate.hs +2/−2
- compiler/GHC/Tc/Utils/TcMType.hs +16/−15
- compiler/GHC/Tc/Utils/Unify.hs +153/−49
- compiler/GHC/Tc/Utils/Zonk.hs +32/−29
- compiler/GHC/Tc/Validity.hs +7/−2
- compiler/GHC/ThToHs.hs +184/−139
- compiler/GHC/Types/Unique/MemoFun.hs +21/−0
- compiler/ghc-llvm-version.h +1/−1
- ghc-lib.cabal +9/−2
- ghc-lib/stage0/compiler/build/primop-primop-info.hs-incl +42/−42
- ghc-lib/stage0/compiler/build/primop-vector-tys.hs-incl +30/−30
- ghc-lib/stage0/rts/build/include/GhclibDerivedConstants.h +4/−4
- ghc-lib/stage0/rts/build/include/ghcautoconf.h +1/−1
compiler/GHC.hs view
@@ -338,7 +338,6 @@ import GHC.Iface.Load ( loadSysInterface ) import GHC.Hs import GHC.Builtin.Types.Prim ( alphaTyVars )-import GHC.Iface.Tidy import GHC.Data.StringBuffer import GHC.Data.FastString import qualified GHC.LanguageExtensions as LangExt@@ -1171,7 +1170,7 @@ type ParsedSource = Located HsModule type RenamedSource = (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)],- Maybe LHsDocString)+ Maybe (LHsDoc GhcRn)) type TypecheckedSource = LHsBinds GhcTc -- NOTE:@@ -1330,12 +1329,12 @@ if simplify then do -- If simplify is true: simplify (hscSimplify), then tidy- -- (tidyProgram).+ -- (hscTidy). hsc_env <- getSession simpl_guts <- liftIO $ do plugins <- readIORef (tcg_th_coreplugins tcg) hscSimplify hsc_env plugins mod_guts- tidy_guts <- liftIO $ tidyProgram hsc_env simpl_guts+ tidy_guts <- liftIO $ hscTidy hsc_env simpl_guts return $ Left tidy_guts else return $ Right mod_guts
compiler/GHC/Builtin/Names/TH.hs view
@@ -594,10 +594,11 @@ quoteTypeName = qqFun (fsLit "quoteType") quoteTypeKey -- data Inline = ...-noInlineDataConName, inlineDataConName, inlinableDataConName :: Name+noInlineDataConName, inlineDataConName, inlinableDataConName, opaqueDataConName :: Name noInlineDataConName = thCon (fsLit "NoInline") noInlineDataConKey inlineDataConName = thCon (fsLit "Inline") inlineDataConKey inlinableDataConName = thCon (fsLit "Inlinable") inlinableDataConKey+opaqueDataConName = thCon (fsLit "Opaque") opaqueDataConKey -- data RuleMatch = ... conLikeDataConName, funLikeDataConName :: Name@@ -700,21 +701,22 @@ -- If you want to change this, make sure you check in GHC.Builtin.Names -- data Inline = ...-noInlineDataConKey, inlineDataConKey, inlinableDataConKey :: Unique+noInlineDataConKey, inlineDataConKey, inlinableDataConKey, opaqueDataConKey :: Unique noInlineDataConKey = mkPreludeDataConUnique 200 inlineDataConKey = mkPreludeDataConUnique 201 inlinableDataConKey = mkPreludeDataConUnique 202+opaqueDataConKey = mkPreludeDataConUnique 203 -- data RuleMatch = ... conLikeDataConKey, funLikeDataConKey :: Unique-conLikeDataConKey = mkPreludeDataConUnique 203-funLikeDataConKey = mkPreludeDataConUnique 204+conLikeDataConKey = mkPreludeDataConUnique 204+funLikeDataConKey = mkPreludeDataConUnique 205 -- data Phases = ... allPhasesDataConKey, fromPhaseDataConKey, beforePhaseDataConKey :: Unique-allPhasesDataConKey = mkPreludeDataConUnique 205-fromPhaseDataConKey = mkPreludeDataConUnique 206-beforePhaseDataConKey = mkPreludeDataConUnique 207+allPhasesDataConKey = mkPreludeDataConUnique 206+fromPhaseDataConKey = mkPreludeDataConUnique 207+beforePhaseDataConKey = mkPreludeDataConUnique 208 -- data Overlap = .. overlappableDataConKey,
compiler/GHC/Builtin/Utils.hs view
@@ -65,6 +65,7 @@ import GHC.Types.Name.Env import GHC.Types.Id.Make import GHC.Types.Unique.FM+import GHC.Types.Unique.Map import GHC.Types.TyThing import GHC.Types.Unique ( isValidKnownKeyUnique ) @@ -80,7 +81,6 @@ import Control.Applicative ((<|>)) import Data.List ( intercalate , find ) import Data.Maybe-import qualified Data.Map as Map {- ************************************************************************@@ -244,15 +244,15 @@ [ availTC n [n] [] | tc <- exposedPrimTyCons, let n = tyConName tc ] -ghcPrimDeclDocs :: DeclDocMap-ghcPrimDeclDocs = DeclDocMap $ Map.fromList $ mapMaybe findName primOpDocs+ghcPrimDeclDocs :: Docs+ghcPrimDeclDocs = emptyDocs { docs_decls = listToUniqMap $ mapMaybe findName primOpDocs } where names = map idName ghcPrimIds ++ map idName allThePrimOpIds ++ map tyConName exposedPrimTyCons findName (nameStr, doc) | Just name <- find ((nameStr ==) . getOccString) names- = Just (name, mkHsDocString doc)+ = Just (name, [WithHsDocIdentifiers (mkGeneratedHsDocString doc) []]) | otherwise = Nothing {-
compiler/GHC/ByteCode/InfoTable.hs view
@@ -10,8 +10,6 @@ import GHC.Prelude -import GHC.Driver.Session- import GHC.Platform import GHC.Platform.Profile
compiler/GHC/ByteCode/Instr.hs view
@@ -223,7 +223,7 @@ char '{' <+> ppr (fst (head bs)) <+> text "= ...; ... }" pprStgAltShort :: OutputablePass pass => StgPprOpts -> GenStgAlt pass -> SDoc-pprStgAltShort opts (con, args, expr) =+pprStgAltShort opts GenStgAlt{alt_con=con, alt_bndrs=args, alt_rhs=expr} = ppr con <+> sep (map ppr args) <+> text "->" <+> pprStgExprShort opts expr pprStgRhsShort :: OutputablePass pass => StgPprOpts -> GenStgRhs pass -> SDoc
compiler/GHC/Cmm/CallConv.hs view
@@ -14,7 +14,6 @@ import GHC.Cmm (Convention(..)) import GHC.Cmm.Ppr () -- For Outputable instances -import GHC.Driver.Session import GHC.Platform import GHC.Platform.Profile import GHC.Utils.Outputable
compiler/GHC/Cmm/Dataflow.hs view
@@ -151,8 +151,8 @@ join = fact_join lattice loop- :: IntHeap -- ^ Worklist, i.e., blocks to process- -> FactBase f -- ^ Current result (increases monotonically)+ :: IntHeap -- Worklist, i.e., blocks to process+ -> FactBase f -- Current result (increases monotonically) -> FactBase f loop todo !fbase1 | Just (index, todo1) <- IntSet.minView todo = let block = block_arr ! index@@ -218,9 +218,9 @@ join = fact_join lattice loop- :: IntHeap -- ^ Worklist, i.e., blocks to process- -> LabelMap (Block node C C) -- ^ Rewritten blocks.- -> FactBase f -- ^ Current facts.+ :: IntHeap -- Worklist, i.e., blocks to process+ -> LabelMap (Block node C C) -- Rewritten blocks.+ -> FactBase f -- Current facts. -> UniqSM (LabelMap (Block node C C), FactBase f) loop todo !blocks1 !fbase1 | Just (index, todo1) <- IntSet.minView todo = do
+ compiler/GHC/Cmm/InitFini.hs view
@@ -0,0 +1,78 @@+-- | Utilities for dealing with constructors/destructors.+module GHC.Cmm.InitFini+ ( InitOrFini(..)+ , isInitOrFiniArray+ ) where++import GHC.Prelude++import GHC.Cmm.CLabel+import GHC.Cmm+import GHC.Utils.Panic+import GHC.Utils.Outputable++{-+Note [Initializers and finalizers in Cmm]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Most platforms support some mechanism for marking a procedure to be run when a+program is loaded (in which case the procedure is known as an "initializer",+"constructor", or "ctor") or unloaded (a "finalizer", "deconstructor", or+"dtor").++For instance, on ELF platforms pointers to initializer and finalizer functions+are listed in .init_array and .fini_array sections, which are traversed by libc+during program startup and shutdown.++In GHC-generated code, initializers are used for a few things:++ * registration of cost-centres and cost-centre stacks for profiling+ * registration of info-table provenance entries+ * registration of ticky tickers+ * registration of HPC ticks++All of these initializers are implemented as C functions, emitted by the+compiler as ForeignStubs. Consequently the GHC.Types.ForeignStubs.CStub type+carries with it lists of functions which should be marked as initializers or+finalizers.++These initializer and finalizer lists are then turned into CmmData declarations+which are fed to the backend. These declarations are distinguished by their+Section (e.g. InitArray or FiniArray) and consist of an array of words, where each+word is a pointer to an initializer/finalizer function. Since this is the same+form that most platforms expect initializer or finalizer lists to appear in+assembler, the NCG backends naturally emit the appropriate assembler.++However, for non-NCG backends (e.g. the C and LLVM backends) these+initializer/finalizer list declarations need to be detected and dealt with+appropriately. We provide isInitOrFiniArray to distinguish such declarations+and turn them back into a list of CLabels.++On Windows initializers/finalizers are a bit tricky due to the inability to+merge objects (due to the lld linker's lack of `-r` support on Windows; see+#21068) since we instead must package foreign stubs into static archives.+However, the linker is free to not include any constituent objects of a static+library in the final object code if nothing depends upon them. Consequently, we+must ensure that the initializer list for a module is defined in the module's+object code, not its foreign stubs. This happens naturally with the plan laid+out above.++Note that we maintain the invariant that at most one initializer and one+finalizer CmmDecl will be emitted per module.+-}++data InitOrFini = IsInitArray | IsFiniArray++isInitOrFiniArray :: RawCmmDecl -> Maybe (InitOrFini, [CLabel])+isInitOrFiniArray (CmmData sect (CmmStaticsRaw _ lits))+ | Just initOrFini <- isInitOrFiniSection sect+ = Just (initOrFini, map get_label lits)+ where+ get_label :: CmmStatic -> CLabel+ get_label (CmmStaticLit (CmmLabel lbl)) = lbl+ get_label static = pprPanic "isInitOrFiniArray: invalid entry" (ppr static)+isInitOrFiniArray _ = Nothing++isInitOrFiniSection :: Section -> Maybe InitOrFini+isInitOrFiniSection (Section InitArray _) = Just IsInitArray+isInitOrFiniSection (Section FiniArray _) = Just IsFiniArray+isInitOrFiniSection _ = Nothing
compiler/GHC/Cmm/Parser.y view
@@ -1519,6 +1519,7 @@ let fstate = F.initFCodeState (profilePlatform $ targetProfile dflags) let fcode = do ((), cmm) <- getCmm $ unEC code "global" (initEnv (targetProfile dflags)) [] >> return ()+ -- See Note [Mapping Info Tables to Source Positions] (IPE Maps) let used_info = map (cmmInfoTableToInfoProvEnt this_mod) (mapMaybe topInfoTable cmm) ((), cmm2) <- getCmm $ mapM_ emitInfoTableProv used_info
compiler/GHC/Cmm/Ppr/Decl.hs view
@@ -166,5 +166,7 @@ ReadOnlyData16 -> text "readonly16" RelocatableReadOnlyData -> text "relreadonly" UninitialisedData -> text "uninitialised"+ InitArray -> text "initarray"+ FiniArray -> text "finiarray" CString -> text "cstring" OtherSection s' -> text s'
compiler/GHC/Cmm/ProcPoint.hs view
@@ -213,7 +213,7 @@ ProcPoint -> 1 ReachedBy ps -> setSize ps block_procpoints = nreached (entryLabel b)- -- | Looking for a successor of b that is reached by+ -- Looking for a successor of b that is reached by -- more proc points than b and is not already a proc -- point. If found, it can become a proc point. newId succ_id = not (setMember succ_id procPoints') &&
compiler/GHC/CmmToAsm/AArch64/CodeGen.hs view
@@ -171,7 +171,7 @@ -- ----------------------------------------------------------------------------- -- | Utilities ann :: SDoc -> Instr -> Instr-ann doc instr {- | debugIsOn -} = ANN doc instr+ann doc instr {- debugIsOn -} = ANN doc instr -- ann _ instr = instr {-# INLINE ann #-} @@ -199,8 +199,8 @@ -- forced until we actually force them, and without -dppr-debug they should -- never end up being forced. annExpr :: CmmExpr -> Instr -> Instr-annExpr e instr {- | debugIsOn -} = ANN (text . show $ e) instr--- annExpr e instr {- | debugIsOn -} = ANN (pprExpr genericPlatform e) instr+annExpr e instr {- debugIsOn -} = ANN (text . show $ e) instr+-- annExpr e instr {- debugIsOn -} = ANN (pprExpr genericPlatform e) instr -- annExpr _ instr = instr {-# INLINE annExpr #-}
compiler/GHC/CmmToAsm/CFG.hs view
@@ -712,7 +712,7 @@ increaseBackEdgeWeight (g_entry graph) $ cfg where - -- | Increase the weight of all backedges in the CFG+ -- Increase the weight of all backedges in the CFG -- this helps to make loop jumpbacks the heaviest edges increaseBackEdgeWeight :: BlockId -> CFG -> CFG increaseBackEdgeWeight root cfg =@@ -725,7 +725,7 @@ in foldl' (\cfg edge -> updateEdgeWeight update edge cfg) cfg backedges - -- | Since we cant fall through info tables we penalize these.+ -- Since we cant fall through info tables we penalize these. penalizeInfoTables :: LabelMap a -> CFG -> CFG penalizeInfoTables info cfg = mapWeights fupdate cfg@@ -736,7 +736,7 @@ = weight - (fromIntegral $ infoTablePenalty weights) | otherwise = weight - -- | If a block has two successors, favour the one with fewer+ -- If a block has two successors, favour the one with fewer -- predecessors and/or the one allowing fall through. favourFewerPreds :: CFG -> CFG favourFewerPreds cfg =
compiler/GHC/CmmToAsm/Dwarf.hs view
@@ -245,7 +245,7 @@ where uws' = addDefaultUnwindings initUws uws nested = concatMap flatten blocks - -- | If the current procedure has an info table, then we also say that+ -- If the current procedure has an info table, then we also say that -- its first block has one to ensure that it gets the necessary -1 -- offset applied to its start address. -- See Note [Info Offset] in "GHC.CmmToAsm.Dwarf.Types".
compiler/GHC/CmmToAsm/PPC/CodeGen.hs view
@@ -2143,12 +2143,14 @@ ] return code where- indexExpr = cmmOffset platform exprWidened offset+ -- See Note [Sub-word subtlety during jump-table indexing] in+ -- GHC.CmmToAsm.X86.CodeGen for why we must first offset, then widen.+ indexExpr0 = cmmOffset platform expr offset -- We widen to a native-width register to santize the high bits- exprWidened = CmmMachOp- (MO_UU_Conv (cmmExprWidth platform expr)- (platformWordWidth platform))- [expr]+ indexExpr = CmmMachOp+ (MO_UU_Conv expr_w (platformWordWidth platform))+ [indexExpr0]+ expr_w = cmmExprWidth platform expr (offset, ids) = switchTargetsToTable targets platform = ncgPlatform config
compiler/GHC/CmmToAsm/PPC/Ppr.hs view
@@ -299,6 +299,8 @@ ReadOnlyData16 -> text ".align 4" -- TODO: This is copied from the ReadOnlyData case, but it can likely be -- made more efficient.+ InitArray -> text ".align 3"+ FiniArray -> text ".align 3" CString | ppc64 -> text ".align 3" | otherwise -> text ".align 2"
compiler/GHC/CmmToAsm/Ppr.hs view
@@ -227,6 +227,14 @@ ReadOnlyData16 | OSMinGW32 <- platformOS platform -> text ".rdata$cst16" | otherwise -> text ".rodata.cst16"+ InitArray+ | OSMinGW32 <- platformOS platform+ -> text ".ctors"+ | otherwise -> text ".init_array"+ FiniArray+ | OSMinGW32 <- platformOS platform+ -> text ".dtors"+ | otherwise -> text ".fini_array" CString | OSMinGW32 <- platformOS platform -> text ".rdata"@@ -251,7 +259,7 @@ ReadOnlyData16 -> text ".csect .text[PR] # ReadOnlyData16" CString -> text ".csect .text[PR] # CString" UninitialisedData -> text ".csect .data[BS]"- OtherSection _ -> panic "pprXcoffSectionHeader: unknown section type"+ _ -> panic "pprXcoffSectionHeader: unknown section type" pprDarwinSectionHeader :: SectionType -> SDoc pprDarwinSectionHeader t = case t of@@ -261,5 +269,7 @@ RelocatableReadOnlyData -> text ".const_data" UninitialisedData -> text ".data" ReadOnlyData16 -> text ".const"+ InitArray -> text ".section\t__DATA,__mod_init_func,mod_init_funcs"+ FiniArray -> panic "pprDarwinSectionHeader: fini not supported" CString -> text ".section\t__TEXT,__cstring,cstring_literals" OtherSection _ -> panic "pprDarwinSectionHeader: unknown section type"
compiler/GHC/CmmToAsm/Reg/Linear.hs view
@@ -385,9 +385,9 @@ , [NatBasicBlock instr]) -- fresh blocks of fixup code. linearRA block_live block_id = go [] [] where- go :: [instr] -- ^ accumulator for instructions already processed.- -> [NatBasicBlock instr] -- ^ accumulator for blocks of fixup code.- -> [LiveInstr instr] -- ^ liveness annotated instructions in this block.+ go :: [instr] -- accumulator for instructions already processed.+ -> [NatBasicBlock instr] -- accumulator for blocks of fixup code.+ -> [LiveInstr instr] -- liveness annotated instructions in this block. -> RegM freeRegs ( [instr] -- instructions after register allocation , [NatBasicBlock instr] ) -- fresh blocks of fixup code.
compiler/GHC/CmmToAsm/X86/CodeGen.hs view
@@ -2773,18 +2773,52 @@ -- ----------------------------------------------------------------------------- -- Generating a table-branch +{-+Note [Sub-word subtlety during jump-table indexing]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Offset the index by the start index of the jump table.+It's important that we do this *before* the widening below. To see+why, consider a switch with a sub-word, signed discriminant such as:++ switch [-5...+2] x::I16 {+ case -5: ...+ ...+ case +2: ...+ }++Consider what happens if we offset *after* widening in the case that+x=-4:++ // x == -4 == 0xfffc::I16+ indexWidened = UU_Conv(x); // == 0xfffc::I64+ indexExpr = indexWidened - (-5); // == 0x10000::I64++This index is clearly nonsense given that the jump table only has+eight entries.++By contrast, if we widen *after* we offset then we get the correct+index (1),++ // x == -4 == 0xfffc::I16+ indexOffset = x - (-5); // == 1::I16+ indexExpr = UU_Conv(indexOffset); // == 1::I64++See #21186.+-}+ genSwitch :: CmmExpr -> SwitchTargets -> NatM InstrBlock genSwitch expr targets = do config <- getConfig let platform = ncgPlatform config- -- We widen to a native-width register because we cannot use arbitry sizes+ expr_w = cmmExprWidth platform expr+ indexExpr0 = cmmOffset platform expr offset+ -- We widen to a native-width register because we cannot use arbitrary sizes -- in x86 addressing modes.- exprWidened = CmmMachOp- (MO_UU_Conv (cmmExprWidth platform expr)- (platformWordWidth platform))- [expr]- indexExpr = cmmOffset platform exprWidened offset+ -- See Note [Sub-word subtlety during jump-table indexing].+ indexExpr = CmmMachOp+ (MO_UU_Conv expr_w (platformWordWidth platform))+ [indexExpr0] if ncgPIC config then do (reg,e_code) <- getNonClobberedReg indexExpr
compiler/GHC/CmmToC.hs view
@@ -40,6 +40,7 @@ import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Utils import GHC.Cmm.Switch+import GHC.Cmm.InitFini import GHC.Types.ForeignCall import GHC.Types.Unique.Set@@ -53,15 +54,12 @@ import Data.ByteString (ByteString) import qualified Data.ByteString as BS-import Control.Monad.ST import Data.Char import Data.List (intersperse) import Data.Map (Map)-import Data.Word import qualified Data.Map as Map import Control.Monad (ap)-import qualified Data.Array.Unsafe as U ( castSTUArray )-import Data.Array.ST+import GHC.Float -- -------------------------------------------------------------------------- -- Now do some real work@@ -103,6 +101,9 @@ -- We only handle (a) arrays of word-sized things and (b) strings. + cmm_data | Just (initOrFini, clbls) <- isInitOrFiniArray cmm_data ->+ pprCtorArray platform initOrFini clbls+ (CmmData section (CmmStaticsRaw lbl [CmmString str])) -> pprExternDecl platform lbl $$ hcat [@@ -269,7 +270,6 @@ hargs = zip args arg_hints need_cdecl- | Just _align <- machOpMemcpyishAlign op = True | MO_ResumeThread <- op = True | MO_SuspendThread <- op = True | otherwise = False@@ -358,7 +358,7 @@ caseify (_ , _ ) = panic "pprSwitch: switch with no cases!" def | Just l <- mbdef = text "default: goto" <+> pprBlockId l <> semi- | otherwise = empty+ | otherwise = text "default: __builtin_unreachable();" -- --------------------------------------------------------------------- -- Expressions.@@ -638,14 +638,15 @@ -- single-word (or smaller) literals. decomposeMultiWord :: CmmLit -> [CmmLit] decomposeMultiWord (CmmFloat n W64)- -- This will produce a W64 integer, which will then be broken up further- -- on the next iteration on 32-bit platforms.- = [doubleToWord64 n]+ | W32 <- wordWidth platform = decomposeMultiWord (doubleToWord64 n)+ | otherwise = [doubleToWord64 n] decomposeMultiWord (CmmFloat n W32) = [floatToWord32 n] decomposeMultiWord (CmmInt n W64) | W32 <- wordWidth platform- = [CmmInt hi W32, CmmInt lo W32]+ = case platformByteOrder platform of+ BigEndian -> [CmmInt hi W32, CmmInt lo W32]+ LittleEndian -> [CmmInt lo W32, CmmInt hi W32] where hi = n `shiftR` 32 lo = n .&. 0xffffffff@@ -930,10 +931,10 @@ MO_F32_Fabs -> text "fabsf" MO_ReadBarrier -> text "load_load_barrier" MO_WriteBarrier -> text "write_barrier"- MO_Memcpy _ -> text "memcpy"- MO_Memset _ -> text "memset"- MO_Memmove _ -> text "memmove"- MO_Memcmp _ -> text "memcmp"+ MO_Memcpy _ -> text "__builtin_memcpy"+ MO_Memset _ -> text "__builtin_memset"+ MO_Memmove _ -> text "__builtin_memmove"+ MO_Memcmp _ -> text "__builtin_memcmp" MO_SuspendThread -> text "suspendThread" MO_ResumeThread -> text "resumeThread"@@ -1410,28 +1411,10 @@ -- can safely initialise to static locations. floatToWord32 :: Rational -> CmmLit-floatToWord32 r- = runST $ do- arr <- newArray_ ((0::Int),0)- writeArray arr 0 (fromRational r)- arr' <- castFloatToWord32Array arr- w32 <- readArray arr' 0- return (CmmInt (toInteger w32) W32)- where- castFloatToWord32Array :: STUArray s Int Float -> ST s (STUArray s Int Word32)- castFloatToWord32Array = U.castSTUArray+floatToWord32 r = CmmInt (toInteger (castFloatToWord32 (fromRational r))) W32 doubleToWord64 :: Rational -> CmmLit-doubleToWord64 r- = runST $ do- arr <- newArray_ ((0::Int),1)- writeArray arr 0 (fromRational r)- arr' <- castDoubleToWord64Array arr- w64 <- readArray arr' 0- return $ CmmInt (toInteger w64) W64- where- castDoubleToWord64Array :: STUArray s Int Double -> ST s (STUArray s Int Word64)- castDoubleToWord64Array = U.castSTUArray+doubleToWord64 r = CmmInt (toInteger (castDoubleToWord64 (fromRational r))) W64 -- ---------------------------------------------------------------------------@@ -1508,3 +1491,19 @@ (q,r) = w' `quotRem` 16 dig | r < 10 = char (chr (fromInteger r + ord '0')) | otherwise = char (chr (fromInteger r - 10 + ord 'a'))++-- | Construct a constructor/finalizer function. Instead of emitting a+-- initializer/finalizer array we rather just emit a single function, annotated+-- with the appropriate C attribute, which then calls each of the initializers.+pprCtorArray :: Platform -> InitOrFini -> [CLabel] -> SDoc+pprCtorArray platform initOrFini lbls =+ decls+ <> text "static __attribute__((" <> attribute <> text "))"+ <> text "void _hs_" <> attribute <> text "()"+ <> braces body+ where+ body = vcat [ pprCLabel platform CStyle lbl <> text " ();" | lbl <- lbls ]+ decls = vcat [ text "void" <+> pprCLabel platform CStyle lbl <> text " (void);" | lbl <- lbls ]+ attribute = case initOrFini of+ IsInitArray -> text "constructor"+ IsFiniArray -> text "destructor"
compiler/GHC/CmmToLlvm.hs view
@@ -65,7 +65,7 @@ when (not (llvmVersionSupported ver) && doWarn) $ putMsg logger $ "You are using an unsupported version of LLVM!" $$ "Currently only" <+> text (llvmVersionStr supportedLlvmVersionLowerBound) <+>- "to" <+> text (llvmVersionStr supportedLlvmVersionUpperBound) <+> "is supported." <+>+ "up to" <+> text (llvmVersionStr supportedLlvmVersionUpperBound) <+> "(non inclusive) is supported." <+> "System LLVM version: " <> text (llvmVersionStr ver) $$ "We will try though..." let isS390X = platformArch (llvmCgPlatform cfg) == ArchS390X
compiler/GHC/CmmToLlvm/CodeGen.hs view
@@ -1738,7 +1738,7 @@ [vx',vy'] -> doExprW ty $ binOp vx' vy' _ -> panic "genMachOp_slow: binCastLlvmOp" - -- | Need to use EOption here as Cmm expects word size results from+ -- Need to use EOption here as Cmm expects word size results from -- comparisons while LLVM return i1. Need to extend to llvmWord type -- if expected. See Note [Literals and branch conditions]. genBinComp opt cmp = do@@ -1761,7 +1761,7 @@ genCastBinMach ty op = binCastLlvmOp ty (LlvmOp op) - -- | Detect if overflow will occur in signed multiply of the two+ -- Detect if overflow will occur in signed multiply of the two -- CmmExpr's. This is the LLVM assembly equivalent of the NCG -- implementation. Its much longer due to type information/safety. -- This should actually compile to only about 3 asm instructions.
compiler/GHC/CmmToLlvm/Data.hs view
@@ -15,6 +15,7 @@ import GHC.Cmm.BlockId import GHC.Cmm.CLabel+import GHC.Cmm.InitFini import GHC.Cmm import GHC.Platform @@ -65,6 +66,14 @@ pure ([LMGlobal aliasDef $ Just orig], [tyAlias]) +-- See Note [Initializers and finalizers in Cmm] in GHC.Cmm.InitFini.+genLlvmData (sect, statics)+ | Just (initOrFini, clbls) <- isInitOrFiniArray (CmmData sect statics)+ = let var = case initOrFini of+ IsInitArray -> fsLit "llvm.global_ctors"+ IsFiniArray -> fsLit "llvm.global_dtors"+ in genGlobalLabelArray var clbls+ genLlvmData (sec, CmmStaticsRaw lbl xs) = do label <- strCLabel_llvm lbl static <- mapM genData xs@@ -88,6 +97,37 @@ return ([globDef], [tyAlias]) +-- | Produce an initializer or finalizer array declaration.+-- See Note [Initializers and finalizers in Cmm] in GHC.Cmm.InitFini for+-- details.+genGlobalLabelArray :: FastString -> [CLabel] -> LlvmM LlvmData+genGlobalLabelArray var_nm clbls = do+ lbls <- mapM strCLabel_llvm clbls+ decls <- mapM mkFunDecl lbls+ let entries = map toArrayEntry lbls+ static = LMStaticArray entries arr_ty+ arr = LMGlobal arr_var (Just static)+ return ([arr], decls)+ where+ mkFunDecl :: LMString -> LlvmM LlvmType+ mkFunDecl fn_lbl = do+ let fn_ty = mkFunTy fn_lbl+ funInsert fn_lbl fn_ty+ return (fn_ty)++ toArrayEntry :: LMString -> LlvmStatic+ toArrayEntry fn_lbl =+ let fn_var = LMGlobalVar fn_lbl (LMPointer $ mkFunTy fn_lbl) Internal Nothing Nothing Global+ fn = LMStaticPointer fn_var+ null = LMStaticLit (LMNullLit i8Ptr)+ prio = LMStaticLit $ LMIntLit 0xffff i32+ in LMStaticStrucU [prio, fn, null] entry_ty++ arr_var = LMGlobalVar var_nm arr_ty Internal Nothing Nothing Global+ mkFunTy lbl = LMFunction $ LlvmFunctionDecl lbl ExternallyVisible CC_Ccc LMVoid FixedArgs [] Nothing+ entry_ty = LMStructU [i32, LMPointer $ mkFunTy $ fsLit "placeholder", LMPointer i8]+ arr_ty = LMArray (length clbls) entry_ty+ -- | Format the section type part of a Cmm Section llvmSectionType :: Platform -> SectionType -> FastString llvmSectionType p t = case t of@@ -106,7 +146,10 @@ CString -> case platformOS p of OSMinGW32 -> fsLit ".rdata$str" _ -> fsLit ".rodata.str"- (OtherSection _) -> panic "llvmSectionType: unknown section type"++ InitArray -> panic "llvmSectionType: InitArray"+ FiniArray -> panic "llvmSectionType: FiniArray"+ OtherSection _ -> panic "llvmSectionType: unknown section type" -- | Format a Cmm Section into a LLVM section name llvmSection :: Section -> LlvmM LMSection
compiler/GHC/Core/Opt/CprAnal.hs view
@@ -20,6 +20,7 @@ import GHC.Types.Id.Info import GHC.Types.Demand import GHC.Types.Cpr+import GHC.Types.Unique.MemoFun import GHC.Core.FamInstEnv import GHC.Core.DataCon@@ -343,7 +344,7 @@ = fst $ cprAnalApp env rhs args -- DataCon worker | Just con <- isDataConWorkId_maybe id- = cprTransformDataConWork (ae_fam_envs env) con args+ = cprTransformDataConWork env con args -- Imported function | otherwise = applyCprTy (getCprSig (idCprSig id)) (length args)@@ -361,20 +362,17 @@ -- | Get a (possibly nested) 'CprType' for an application of a 'DataCon' worker, -- given a saturated number of 'CprType's for its field expressions. -- Implements the Nested part of Note [Nested CPR].-cprTransformDataConWork :: FamInstEnvs -> DataCon -> [(CprType, CoreArg)] -> CprType-cprTransformDataConWork fam_envs con args+cprTransformDataConWork :: AnalEnv -> DataCon -> [(CprType, CoreArg)] -> CprType+cprTransformDataConWork env con args | null (dataConExTyCoVars con) -- No existentials , wkr_arity <= mAX_CPR_SIZE -- See Note [Trimming to mAX_CPR_SIZE] , args `lengthIs` wkr_arity- , isRecDataCon fam_envs fuel con /= DefinitelyRecursive -- See Note [CPR for recursive data constructors]+ , ae_rec_dc env con /= DefinitelyRecursive -- See Note [CPR for recursive data constructors] -- , pprTrace "cprTransformDataConWork" (ppr con <+> ppr wkr_arity <+> ppr args) True = CprType 0 (ConCpr (dataConTag con) (strictZipWith extract_nested_cpr args wkr_str_marks)) | otherwise = topCprType where- fuel = 3 -- If we can unbox more than 3 constructors to find a- -- recursive occurrence, then we can just as well unbox it- -- See Note [CPR for recursive data constructors], point (4) wkr_arity = dataConRepArity con wkr_str_marks = dataConRepStrictness con -- See Note [Nested CPR]@@ -430,6 +428,31 @@ where (id', rhs', env') = cprAnalBind env id rhs +{-+Note [The OPAQUE pragma and avoiding the reboxing of results]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider:++ {-# OPAQUE f #-}+ f x = (x,y)++ g True = f 2 x+ g False = (0,0)++Where if we didn't strip the CPR info from 'f' we would end up with the+following W/W pair for 'g':++ $wg True = case f 2 of (x, y) -> (# x, y #)+ $wg False = (# 0, 0 #)++ g b = case wg$ b of (# x, y #) -> (x, y)++Where the worker unboxes the result of 'f', only for wrapper to box it again.+That's because the non-stripped CPR signature of 'f' is saying to W/W-transform+'f'. However, OPAQUE-annotated binders aren't W/W transformed (see+Note [OPAQUE pragma]), so we should strip 'f's CPR signature.+-}+ -- | Process the RHS of the binding for a sensible arity, add the CPR signature -- to the Id, and augment the environment with the signature as well. cprAnalBind@@ -454,8 +477,12 @@ | otherwise = rhs_ty -- See Note [Arity trimming for CPR signatures] sig = mkCprSigForArity (idArity id) rhs_ty'- id' = setIdCprSig id sig- env' = extendSigEnv env id sig+ -- See Note [OPAQUE pragma]+ -- See Note [The OPAQUE pragma and avoiding the reboxing of results]+ sig' | isOpaquePragma (idInlinePragma id) = topCprSig+ | otherwise = sig+ id' = setIdCprSig id sig'+ env' = extendSigEnv env id sig' -- See Note [CPR for thunks] stays_thunk = is_thunk && not_strict@@ -563,6 +590,8 @@ -- iteration. See Note [Initialising strictness] in "GHC.Core.Opt.DmdAnal" , ae_fam_envs :: FamInstEnvs -- ^ Needed when expanding type families and synonyms of product types.+ , ae_rec_dc :: DataCon -> IsRecDataConResult+ -- ^ Memoised result of 'GHC.Core.Opt.WorkWrap.Utils.isRecDataCon' } instance Outputable AnalEnv where@@ -594,7 +623,11 @@ { ae_sigs = SE emptyUnVarSet emptyVarEnv , ae_virgin = True , ae_fam_envs = fam_envs- }+ , ae_rec_dc = memoiseUniqueFun (isRecDataCon fam_envs fuel)+ } where+ fuel = 3 -- If we can unbox more than 3 constructors to find a+ -- recursive occurrence, then we can just as well unbox it+ -- See Note [CPR for recursive data constructors], point (4) modifySigEnv :: (SigEnv -> SigEnv) -> AnalEnv -> AnalEnv modifySigEnv f env = env { ae_sigs = f (ae_sigs env) }@@ -985,43 +1018,47 @@ Note [CPR for recursive data constructors]? That is up to 'GHC.Core.Opt.WorkWrapW.Utils.isRecDataCon' to decide. It does a DFS search over the field types of the DataCon and looks for term-level recursion into the data-constructor's type constructor. A few perhaps surprising points:+constructor's type constructor. Assuming infinite fuel (point (4) below), it+looks inside the following class of types, represented by `ty` (and responds+`NonRecursiveOrUnsure` in all other cases): + A. If `ty = forall v. ty'`, then look into `ty'`+ B. If `ty = Tc tc_args` and `Tc` is an `AlgTyCon`, look into the arg+ types of its data constructors and check `tc_args` for recursion.+ C. If `ty = F tc_args`, `F` is a `FamTyCon` and we can reduce `F tc_args` to+ `rhs`, look into the `rhs` type.++A few perhaps surprising points:+ 1. It deems any function type as non-recursive, because it's unlikely that a recursion through a function type builds up a recursive data structure. 2. It doesn't look into kinds or coercion types because there's nothing to unbox. Same for promoted data constructors.- 3. We don't care whether a NewTyCon or DataTyCon App is fully saturated or not;- we simply look at its definition/DataCons and its field tys. Any recursive arg- occs will have been detected before (see the invariant of 'go_tc_app').- This is so that we expand the `ST` in `StateT Int (ST s) a`.+ 3. We don't care whether an AlgTyCon app `T tc_args` is fully saturated or not;+ we simply look at its definition/DataCons and its field tys and look for+ recursive occs in the `tc_args` we are given. This is so that we expand+ the `ST` in `StateT Int (ST s) a`. 4. We don't recurse deeper than 3 (at the moment of this writing) TyCons and- assume the DataCon is non-recursive after that. One reason is guaranteed- constant-time efficiency; the other is that it's fair to say that a recursion- over 3 or more TyCons doesn't really count as a list-like data structure- anymore and a bit of unboxing doesn't hurt much.- 5. It checks TyConApps like `T <huge> <type>` by eagerly checking the- potentially huge argument types *before* it tries to expand the- DataCons/NewTyCon/TyFams/etc. so that it doesn't need to re-check those- argument types after having been substituted into every occurrence of- the the respective TyCon parameter binders. It's like call-by-value vs.- call-by-name: Eager checking of argument types means we only need to check- them exactly once.- There's one exception to that rule, namely when we are able to reduce a- TyFam by considering argument types. Then we pay the price of potentially- checking the same type arg twice (or more, if the TyFam is recursive).- It should hardly matter.+ assume the DataCon is non-recursive after that. One reason for this "fuel"+ approach is guaranteed constant-time efficiency; the other is that it's+ fair to say that a recursion over 3 or more TyCons doesn't really count as+ a list-like data structure anymore and a bit of unboxing doesn't hurt much.+ 5. It checks AlgTyCon apps like `T tc_args` by eagerly checking the `tc_args`+ *before* it looks into the expanded DataCons/NewTyCon, so that it+ terminates before doing a deep nest of expansions only to discover that the+ first level already contained a recursion. 6. As a result of keeping the implementation simple, it says "recursive" for `data T = MkT [T]`, even though we could argue that the inner recursion (through the `[]` TyCon) by way of which `T` is recursive will already be "broken" and thus never unboxed. Consequently, it might be OK to CPR a function returning `T`. Lacking arguments for or against the current simple behavior, we stick to it.- 7. When the search hits an abstract TyCon (one without visible DataCons, e.g.,- from an .hs-boot file), it returns 'Nothing' for "inconclusive", the same- as when we run out of fuel. If there is ever a recursion through an- abstract TyCon, then it's not part of the same function we are looking at,- so we can treat it as if it wasn't recursive.+ 7. When the search hits an abstract TyCon (algebraic, but without visible+ DataCons, e.g., from an .hs-boot file), it returns 'NonRecursiveOrUnsure',+ the same as when we run out of fuel. If there is ever a recursion through+ an abstract TyCon, then it's not part of the same function we are looking+ at in CPR, so we can treat it as if it wasn't recursive.+ We handle stuck type and data families much the same. Here are a few examples of data constructors or data types with a single data con and the answers of our function:@@ -1044,12 +1081,12 @@ E Int = Char E (a,b) = (E a, E b) E Char = Blub- data Blah = Blah (E (Int, (Int, Int))) NonRec (see point (5))+ data Blah = Blah (E (Int, (Int, Int))) NonRec data Blub = Blub (E (Char, Int)) Rec- data Blub2 = Blub2 (E (Bool, Int)) } Rec, because stuck+ data Blub2 = Blub2 (E (Bool, Int)) } Unsure, because stuck (see point (7)) { data T1 = T1 T2; data T2 = T2 T3;- ... data T5 = T5 T1 } Nothing (out of fuel) (see point (4))+ ... data T5 = T5 T1 } Unsure (out of fuel) (see point (4)) { module A where -- A.hs-boot data T@@ -1057,7 +1094,7 @@ import {-# SOURCE #-} A data U = MkU T f :: T -> U- f t = MkU t Nothing (T is abstract) (see point (7))+ f t = MkU t Unsure (T is abstract) (see point (7)) module A where -- A.hs import B data T = MkT U }
compiler/GHC/Core/Opt/DmdAnal.hs view
@@ -40,10 +40,11 @@ import GHC.Utils.Misc import GHC.Utils.Panic import GHC.Utils.Panic.Plain-import GHC.Data.Maybe ( isJust, orElse )+import GHC.Data.Maybe import GHC.Builtin.PrimOps import GHC.Builtin.Types.Prim ( realWorldStatePrimTy ) import GHC.Types.Unique.Set+import GHC.Types.Unique.MemoFun import GHC.Utils.Trace _ = pprTrace -- Tired of commenting out the import all the time@@ -96,7 +97,7 @@ add_exported_uses :: AnalEnv -> DmdType -> [Id] -> DmdType add_exported_uses env = foldl' (add_exported_use env) - -- | If @e@ is denoted by @dmd_ty@, then @add_exported_use _ dmd_ty id@+ -- If @e@ is denoted by @dmd_ty@, then @add_exported_use _ dmd_ty id@ -- corresponds to the demand type of @(id, e)@, but is a lot more direct. -- See Note [Analysing top-level bindings]. add_exported_use :: AnalEnv -> DmdType -> Id -> DmdType@@ -352,7 +353,7 @@ -- NB: (:*) expands AbsDmd and BotDmd as needed -- See Note [Analysing with absent demand] | WithDmdType dmd_ty e' <- dmdAnal env sd e- = assertPpr (not (isUnliftedType (exprType e)) || exprOkForSpeculation e) (ppr e)+ = assertPpr (mightBeLiftedType (exprType e) || exprOkForSpeculation e) (ppr e) -- The argument 'e' should satisfy the let/app invariant (toPlusDmdArg $ multDmdType n dmd_ty, e') @@ -428,8 +429,9 @@ dmdAnal' env dmd (Case scrut case_bndr ty [Alt alt bndrs rhs]) -- Only one alternative.- -- If it's a DataAlt, it should be the only constructor of the type.- | is_single_data_alt alt+ -- If it's a DataAlt, it should be the only constructor of the type and we+ -- can consider its field demands when analysing the scrutinee.+ | want_precise_field_dmds alt = let WithDmdType rhs_ty rhs' = dmdAnal env dmd rhs WithDmdType alt_ty1 fld_dmds = findBndrsDmds env rhs_ty bndrs@@ -454,10 +456,9 @@ -- __DEFAULT and literal alts. Simply add demands and discard the -- evaluation cardinality, as we evaluate the scrutinee exactly once. = assert (null bndrs) (bndrs, case_bndr_sd)- fam_envs = ae_fam_envs env alt_ty3 -- See Note [Precise exceptions and strictness analysis] in "GHC.Types.Demand"- | exprMayThrowPreciseException fam_envs scrut+ | exprMayThrowPreciseException (ae_fam_envs env) scrut = deferAfterPreciseException alt_ty2 | otherwise = alt_ty2@@ -474,8 +475,12 @@ -- , text "res_ty" <+> ppr res_ty ]) $ WithDmdType res_ty (Case scrut' case_bndr' ty [Alt alt bndrs' rhs']) where- is_single_data_alt (DataAlt dc) = isJust $ tyConSingleAlgDataCon_maybe $ dataConTyCon dc- is_single_data_alt _ = True+ want_precise_field_dmds alt = case alt of+ (DataAlt dc)+ | Nothing <- tyConSingleAlgDataCon_maybe $ dataConTyCon dc -> False+ | DefinitelyRecursive <- ae_rec_dc env dc -> False+ -- See Note [Demand analysis for recursive data constructors]+ _ -> True @@ -689,12 +694,29 @@ from 'topDiv' to 'conDiv', leading to bugs, performance regressions and complexity that didn't justify the single fixed testcase T13380c. +Note [Demand analysis for recursive data constructors]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+T11545 features a single-product, recursive data type+ data A = A A A ... A+ deriving Eq+Naturally, `(==)` is deeply strict in `A` and in fact will never terminate. That+leads to very large (exponential in the depth) demand signatures and fruitless+churn in boxity analysis, demand analysis and worker/wrapper.+So we detect `A` as a recursive data constructor+(see Note [Detecting recursive data constructors]) analysing `case x of A ...`+and simply assume L for the demand on field binders, which is the same code+path as we take for sum types.+Combined with the B demand on the case binder, we get the very small demand+signature <1S><1S>b on `(==)`. This improves ghc/alloc performance on T11545+tenfold! See also Note [CPR for recursive data constructors] which describes the+sibling mechanism in CPR analysis.+ Note [Demand on the scrutinee of a product case] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When figuring out the demand on the scrutinee of a product case, we use the demands of the case alternative, i.e. id_dmds. But note that these include the demand on the case binder;-see Note [Demand on case-alternative binders] in GHC.Types.Demand.+see Note [Demand on case-alternative binders]. This is crucial. Example: f x = case x of y { (a,b) -> k y a } If we just take scrut_demand = 1P(L,A), then we won't pass x to the@@ -869,7 +891,7 @@ -- to the Id, and augment the environment with the signature as well. -- See Note [NOINLINE and strictness] dmdAnalRhsSig top_lvl rec_flag env let_dmd id rhs- = -- pprTrace "dmdAnalRhsSig" (ppr id $$ ppr let_dmd $$ ppr sig $$ ppr lazy_fv) $+ = -- pprTrace "dmdAnalRhsSig" (ppr id $$ ppr let_dmd $$ ppr rhs_dmds $$ ppr sig $$ ppr lazy_fv) $ (final_env, lazy_fv, final_id, final_rhs) where rhs_arity = idArity id@@ -882,15 +904,17 @@ -- See Note [Demand analysis for join points] -- See Note [Invariants on join points] invariant 2b, in GHC.Core -- rhs_arity matches the join arity of the join point- = let_dmd+ -- See Note [Unboxed demand on function bodies returning small products]+ = unboxedWhenSmall env rec_flag (resultType_maybe id) let_dmd | otherwise -- See Note [Unboxed demand on function bodies returning small products]- = unboxedWhenSmall (ae_opts env) (unboxableResultWidth env id) topSubDmd+ = unboxedWhenSmall env rec_flag (resultType_maybe id) topSubDmd - -- See Note [Do not unbox class dictionaries] WithDmdType rhs_dmd_ty rhs' = dmdAnal env rhs_dmd rhs- DmdType rhs_fv rhs_dmds rhs_div = rhs_dmd_ty- (final_rhs_dmds, final_rhs) = finaliseArgBoxities env id rhs_arity rhs'+ DmdType rhs_fv rhs_dmds rhs_div = rhs_dmd_ty+ -- See Note [Do not unbox class dictionaries]+ -- See Note [Boxity for bottoming functions]+ (final_rhs_dmds, final_rhs) = finaliseArgBoxities env id rhs_arity rhs' rhs_div `orElse` (rhs_dmds, rhs') sig = mkDmdSigForArity rhs_arity (DmdType sig_fv final_rhs_dmds rhs_div)@@ -920,26 +944,45 @@ -- See Note [Lazy and unleashable free variables] !(!lazy_fv, !sig_fv) = partitionVarEnv isWeakDmd rhs_fv2 -unboxableResultWidth :: AnalEnv -> Id -> Maybe Arity-unboxableResultWidth env id+-- | The result type after applying 'idArity' many arguments. Returns 'Nothing'+-- when the type doesn't have exactly 'idArity' many arrows.+resultType_maybe :: Id -> Maybe Type+resultType_maybe id | (pis,ret_ty) <- splitPiTys (idType id) , count (not . isNamedBinder) pis == idArity id- , Just (tc, _tc_args, _co) <- normSplitTyConApp_maybe (ae_fam_envs env) ret_ty- , Just dc <- tyConSingleAlgDataCon_maybe tc- , null (dataConExTyCoVars dc) -- Can't unbox results with existentials- = Just (dataConRepArity dc)+ = Just $! ret_ty | otherwise = Nothing -unboxedWhenSmall :: DmdAnalOpts -> Maybe Arity -> SubDemand -> SubDemand+unboxedWhenSmall :: AnalEnv -> RecFlag -> Maybe Type -> SubDemand -> SubDemand -- See Note [Unboxed demand on function bodies returning small products]-unboxedWhenSmall opts mb_n sd- | Just n <- mb_n- , n <= dmd_unbox_width opts- = unboxSubDemand sd- | otherwise- = sd+unboxedWhenSmall _ _ Nothing sd = sd+unboxedWhenSmall env rec_flag (Just ret_ty) sd = go 1 ret_ty sd+ where+ -- Magic constant, bounding the depth of optimistic 'Unboxed' flags. We+ -- might want to minmax in the future.+ max_depth | isRec rec_flag = 3 -- So we get at most something as deep as !P(L!P(L!L))+ | otherwise = 1 -- Otherwise be unbox too deep in T18109, T18174 and others and get a bunch of stack overflows+ go :: Int -> Type -> SubDemand -> SubDemand+ go depth ty sd+ | depth <= max_depth+ , Just (tc, tc_args, _co) <- normSplitTyConApp_maybe (ae_fam_envs env) ty+ , Just dc <- tyConSingleAlgDataCon_maybe tc+ , null (dataConExTyCoVars dc) -- Can't unbox results with existentials+ , dataConRepArity dc <= dmd_unbox_width (ae_opts env)+ , Just (_, ds) <- viewProd (dataConRepArity dc) sd+ , arg_tys <- map scaledThing $ dataConInstArgTys dc tc_args+ , equalLength ds arg_tys+ = mkProd Unboxed $! strictZipWith (go_dmd (depth+1)) arg_tys ds+ | otherwise+ = sd + go_dmd :: Int -> Type -> Demand -> Demand+ go_dmd depth ty dmd = case dmd of+ AbsDmd -> AbsDmd+ BotDmd -> BotDmd+ n :* sd -> n :* go depth ty sd+ -- | If given the (local, non-recursive) let-bound 'Id', 'useLetUp' determines -- whether we should process the binding up (body before rhs) or down (rhs -- before body).@@ -1157,6 +1200,69 @@ (since it is apparently Absent) and then inline (\x. fst g) we get disaster. But regardless, #18638 was a more complicated version of this, that actually happened in practice.++Note [Boxity for bottoming functions]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider+```hs+indexError :: Show a => (a, a) -> a -> String -> b+-- Str=<..><1!P(S,S)><1S><S>b+indexError rng i s = error (show rng ++ show i ++ show s)++get :: (Int, Int) -> Int -> [a] -> a+get p@(l,u) i xs+ | l <= i, i < u = xs !! (i-u)+ | otherwise = indexError p i "get"+```+The hot path of `get` certainly wants to unbox `p` as well as `l` and `u`, but+the unimportant, diverging error path needs `l` and `u` boxed (although the+wrapper for `indexError` *will* unbox `p`). This pattern often occurs in+performance sensitive code that does bounds-checking.++It would be a shame to let `Boxed` win for the fields! So here's what we do:+While to summarising `indexError`'s boxity signature in `finaliseArgBoxities`,+we `unboxDeeplyDmd` all its argument demands and are careful not to discard+excess boxity in the `StopUnboxing` case, to get the signature+`<1!P(!S,!S)><1!S><S!S>b`.++Then worker/wrapper will not only unbox the pair passed to `indexError` (as it+would do anyway), demand analysis will also pretend that `indexError` needs `l`+and `u` unboxed (and the two other args). Which is a lie, because `indexError`'s+type abstracts over their types and could never unbox them.++The important change is at the *call sites* of `$windexError`: Boxity analysis+will conclude to unbox `l` and `u`, which *will* incur reboxing of crud that+should better float to the call site of `$windexError`. There we don't care+much, because it's in the slow, diverging code path! And that floating often+happens, but not always. See Note [Reboxed crud for bottoming calls].++Note [Reboxed crud for bottoming calls]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+For functions like `get` in Note [Boxity for bottoming functions], it's clear+that the reboxed crud will be floated inside to the call site of `$windexError`.+But here's an example where that is not the case:+```hs+import GHC.Ix++theresCrud :: Int -> Int -> Int+theresCrud x y = go x+ where+ go 0 = index (0,y) 0+ go 1 = index (x,y) 1+ go n = go (n-1)+ {-# NOINLINE theresCrud #-}+```+If you look at the Core, you'll see that `y` will be reboxed and used in the+two exit join points for the `$windexError` calls, while `x` is only reboxed in the+exit join point for `index (x,y) 1` (happens in lvl below):+```+$wtheresCrud = \ ww ww1 ->+ let { y = I# ww1 } in+ join { lvl2 = ... case lvl1 ww y of wild { }; ... } in+ join { lvl3 = ... case lvl y of wild { }; ... } in+ ...+```+This is currently a bug that we willingly accept and it's documented in #21128. -} {- *********************************************************************@@ -1410,6 +1516,24 @@ To achieve this, we use the classic almost-circular programming technique in which we we write one pass that takes a lazy list of the Budgets for every layer.++Note [The OPAQUE pragma and avoiding the reboxing of arguments]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In https://gitlab.haskell.org/ghc/ghc/-/issues/13143 it was identified that when+a function 'f' with a NOINLINE pragma is W/W transformed, then the worker for+'f' should get the NOINLINE annotation, while the wrapper /should/ be inlined.++That's because if the wrapper for 'f' had stayed NOINLINE, then any worker of a+W/W-transformed /caller of/ 'f' would immediately rebox any unboxed arguments+that is applied to the wrapper of 'f'. When the wrapper is inlined, that kind of+reboxing does not happen.++But now we have functions with OPAQUE pragmas, which by definition (See Note+[OPAQUE pragma]) do not get W/W-transformed. So in order to avoid reboxing+workers of any W/W-transformed /callers of/ 'f' we need to strip all boxity+information from 'f' in the demand analysis. This will inform the+W/W-transformation code that boxed arguments of 'f' must definitely be passed+along in boxed form and as such dissuade the creation of reboxing workers. -} data Budgets = MkB Arity Budgets -- An infinite list of arity budgets@@ -1420,9 +1544,9 @@ positiveTopBudget :: Budgets -> Bool positiveTopBudget (MkB n _) = n >= 0 -finaliseArgBoxities :: AnalEnv -> Id -> Arity -> CoreExpr+finaliseArgBoxities :: AnalEnv -> Id -> Arity -> CoreExpr -> Divergence -> Maybe ([Demand], CoreExpr)-finaliseArgBoxities env fn arity rhs+finaliseArgBoxities env fn arity rhs div | arity > count isId bndrs -- Can't find enough binders = Nothing -- This happens if we have f = g -- Then there are no binders; we don't worker/wrapper; and we@@ -1453,13 +1577,20 @@ mk_triple :: Id -> (Type,StrictnessMark,Demand) mk_triple bndr | is_cls_arg ty = (ty, NotMarkedStrict, trimBoxity dmd)+ | is_bot_fn = (ty, NotMarkedStrict, unboxDeeplyDmd dmd)+ -- See Note [OPAQUE pragma]+ -- See Note [The OPAQUE pragma and avoiding the reboxing of arguments]+ | is_opaque = (ty, NotMarkedStrict, trimBoxity dmd) | otherwise = (ty, NotMarkedStrict, dmd) where- ty = idType bndr- dmd = idDemandInfo bndr+ ty = idType bndr+ dmd = idDemandInfo bndr+ is_opaque = isOpaquePragma (idInlinePragma fn) -- is_cls_arg: see Note [Do not unbox class dictionaries] is_cls_arg arg_ty = is_inlinable_fn && isClassPred arg_ty+ -- is_bot_fn: see Note [Boxity for bottoming functions]+ is_bot_fn = div == botDiv go_args :: Budgets -> [(Type,StrictnessMark,Demand)] -> (Budgets, [Demand]) go_args bg triples = mapAccumL go_arg bg triples@@ -1467,8 +1598,11 @@ go_arg :: Budgets -> (Type,StrictnessMark,Demand) -> (Budgets, Demand) go_arg bg@(MkB bg_top bg_inner) (ty, str_mark, dmd@(n :* _)) = case wantToUnboxArg False fam_envs ty dmd of- DropAbsent -> (bg, dmd)- StopUnboxing -> (MkB (bg_top-1) bg_inner, trimBoxity dmd)+ StopUnboxing+ | not is_bot_fn+ -- If bot: Keep deep boxity even though WW won't unbox+ -- See Note [Boxity for bottoming functions]+ -> (MkB (bg_top-1) bg_inner, trimBoxity dmd) Unbox DataConPatContext{dcpc_dc=dc, dcpc_tc_args=tc_args} dmds -> (MkB (bg_top-1) final_bg_inner, final_dmd)@@ -1484,10 +1618,13 @@ -- isStrict: see Note [No lazy, Unboxed demands in demand signature] -- isMarkedStrict: see Note [Unboxing evaluated arguments] , positiveTopBudget bg_inner'+ , NonRecursiveOrUnsure <- ae_rec_dc env dc+ -- See Note [Which types are unboxed?]+ -- and Note [Demand analysis for recursive data constructors] = (bg_inner', dmd') | otherwise = (bg_inner, trimBoxity dmd)- Unlift -> panic "No unlifting in DmdAnal"+ _ -> (bg, dmd) add_demands :: [Demand] -> CoreExpr -> CoreExpr -- Attach the demands to the outer lambdas of this expression@@ -1817,12 +1954,15 @@ data AnalEnv = AE- { ae_opts :: !DmdAnalOpts -- ^ Analysis options- , ae_sigs :: !SigEnv- , ae_virgin :: !Bool -- ^ True on first iteration only- -- See Note [Initialising strictness]- , ae_fam_envs :: !FamInstEnvs- }+ { ae_opts :: !DmdAnalOpts+ -- ^ Analysis options+ , ae_sigs :: !SigEnv+ , ae_virgin :: !Bool+ -- ^ True on first iteration only. See Note [Initialising strictness]+ , ae_fam_envs :: !FamInstEnvs+ , ae_rec_dc :: DataCon -> IsRecDataConResult+ -- ^ Memoised result of 'GHC.Core.Opt.WorkWrap.Utils.isRecDataCon'+ } -- We use the se_env to tell us whether to -- record info about a variable in the DmdEnv@@ -1845,6 +1985,7 @@ , ae_sigs = emptySigEnv , ae_virgin = True , ae_fam_envs = fam_envs+ , ae_rec_dc = memoiseUniqueFun (isRecDataCon fam_envs 3) } emptySigEnv :: SigEnv
compiler/GHC/Core/Opt/Exitify.hs view
@@ -131,11 +131,11 @@ -- variables bound on the way and lifts it out as a join point. -- -- ExitifyM is a state monad to keep track of floated binds- go :: [Var] -- ^ Variables that are in-scope here, but+ go :: [Var] -- Variables that are in-scope here, but -- not in scope at the joinrec; that is, -- we must potentially abstract over them. -- Invariant: they are kept in dependency order- -> CoreExprWithFVs -- ^ Current expression in tail position+ -> CoreExprWithFVs -- Current expression in tail position -> ExitifyM CoreExpr -- We first look at the expression (no matter what it shape is)
compiler/GHC/Core/Opt/FloatIn.hs view
@@ -27,7 +27,7 @@ import GHC.Core.FVs import GHC.Core.Type -import GHC.Types.Basic ( RecFlag(..), isRec )+import GHC.Types.Basic ( RecFlag(..), isRec, Levity(Unlifted) ) import GHC.Types.Id ( isOneShotBndr, idType, isJoinId, isJoinId_maybe ) import GHC.Types.Tickish import GHC.Types.Var@@ -448,6 +448,7 @@ fiExpr platform to_drop (_, AnnCase scrut case_bndr _ [AnnAlt con alt_bndrs rhs]) | isUnliftedType (idType case_bndr)+ -- binders have a fixed RuntimeRep so it's OK to call isUnliftedType , exprOkForSideEffects (deAnnotate scrut) -- See Note [Floating primops] = wrapFloats shared_binds $@@ -592,7 +593,7 @@ noFloatIntoArg :: CoreExprWithFVs' -> Type -> Bool noFloatIntoArg expr expr_ty- | isUnliftedType expr_ty+ | Just Unlifted <- typeLevity_maybe expr_ty = True -- See Note [Do not destroy the let/app invariant] | AnnLam bndr e <- expr
compiler/GHC/Core/Opt/FloatOut.hs view
@@ -269,6 +269,8 @@ = go [] [] (bagToList fs) where go ul_prs prs (FloatLet (NonRec b r) : fs) | isUnliftedType (idType b)+ -- NB: isUnliftedType is OK here as binders always+ -- have a fixed RuntimeRep. , not (isJoinId b) = go ((b,r):ul_prs) prs fs | otherwise
compiler/GHC/Core/Opt/Simplify.hs view
@@ -574,25 +574,40 @@ Its not wrong to drop it on the floor, but better to keep it. -Note [Cast w/w: unlifted]-~~~~~~~~~~~~~~~~~~~~~~~~~-BUT don't do cast worker/wrapper if 'e' has an unlifted type.-This *can* happen:+Note [Preserve RuntimeRep info in cast w/w]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We must not do cast w/w when the presence of the coercion is needed in order+to determine the runtime representation. - foo :: Int = (error (# Int,Int #) "urk")- `cast` CoUnsafe (# Int,Int #) Int+Example: -If do the makeTrivial thing to the error call, we'll get- foo = case error (# Int,Int #) "urk" of v -> v `cast` ...-But 'v' isn't in scope!+ Suppose we have a type family: -These strange casts can happen as a result of case-of-case- bar = case (case x of { T -> (# 2,3 #); F -> error "urk" }) of- (# p,q #) -> p+q+ type F :: RuntimeRep+ type family F where+ F = LiftedRep -NOTE: Nowadays we don't use casts for these error functions;-instead, we use (case erorr ... of {}). So I'm not sure-this Note makes much sense any more.+ together with a type `ty :: TYPE F` and a top-level binding++ a :: ty |> TYPE F[0]++ The kind of `ty |> TYPE F[0]` is `LiftedRep`, so `a` is a top-level lazy binding.+ However, were we to apply cast w/w, we would get:++ b :: ty+ b = ...++ a :: ty |> TYPE F[0]+ a = b `cast` GRefl (TYPE F[0])++ Now we are in trouble because `ty :: TYPE F` does not have a known runtime+ representation, because we need to be able to reduce the nullary type family+ application `F` to find that out.++Conclusion: only do cast w/w when doing so would not lose the RuntimeRep+information. That is, when handling `Cast rhs co`, don't attempt cast w/w+unless the kind of the type of rhs is concrete, in the sense of+Note [Concrete types] in GHC.Tc.Utils.Concrete. -} tryCastWorkerWrapper :: SimplEnv -> TopLevelFlag@@ -606,8 +621,11 @@ -- a DFunUnfolding in mk_worker_unfolding , not (exprIsTrivial rhs) -- Not x = y |> co; Wrinkle 1 , not (hasInlineUnfolding info) -- Not INLINE things: Wrinkle 4- , not (isUnliftedType rhs_ty) -- Not if rhs has an unlifted type;- -- see Note [Cast w/w: unlifted]+ , isConcrete (typeKind rhs_ty) -- Don't peel off a cast if doing so would+ -- lose the underlying runtime representation.+ -- See Note [Preserve RuntimeRep info in cast w/w]+ , not (isOpaquePragma (idInlinePragma old_bndr)) -- Not for OPAQUE bindings+ -- See Note [OPAQUE pragma] = do { (rhs_floats, work_rhs) <- prepareRhs env top_lvl occ_fs rhs ; uniq <- getUniqueM ; let work_name = mkSystemVarName uniq occ_fs@@ -2850,6 +2868,7 @@ = isTyCoArg scrut -- Note [Core type and coercion invariant] | isUnliftedType (idType case_bndr)+ -- OK to call isUnliftedType: scrutinees always have a fixed RuntimeRep (see FRRCase) = exprOkForSpeculation scrut | otherwise -- Scrut has a lifted type
compiler/GHC/Core/Opt/Simplify/Env.hs view
@@ -526,6 +526,8 @@ -- See Note [Core top-level string literals] in GHC.Core. | exprOkForSpeculation rhs = FltOkSpec -- Unlifted, and lifted but ok-for-spec (eg HNF) | otherwise = assertPpr (not (isUnliftedType (idType bndr))) (ppr bndr)+ -- NB: binders always have a fixed RuntimeRep, so calling+ -- isUnliftedType is OK here FltCareful -- Unlifted binders can only be let-bound if exprOkForSpeculation holds
compiler/GHC/Core/Opt/Simplify/Utils.hs view
@@ -590,21 +590,14 @@ | Just (_, arg_ty, fun_ty') <- splitFunTy_maybe fun_ty -- Add strict-type info , dmd : rest_dmds <- dmds , let dmd'- -- TODO: we should just use isLiftedType_maybe, but that- -- function is currently wrong (#20837).- | Just rr <- getRuntimeRep_maybe arg_ty- , Just False <- isLiftedRuntimeRep_maybe rr- -- The type is definitely unlifted, such as:- -- - TYPE (BoxedRep Unlifted)- -- - TYPE IntRep, TYPE FloatRep, ...+ | Just Unlifted <- typeLevity_maybe arg_ty = strictifyDmd dmd | otherwise- -- Could be definitely lifted, or we're not sure (e.g. levity-polymorphic).+ -- Something that's not definitely unlifted.+ -- If the type is representation-polymorphic, we can't know whether+ -- it's strict. = dmd = dmd' : add_type_strictness fun_ty' rest_dmds- -- If the type is representation-polymorphic, we can't know whether- -- it's strict. isLiftedType_maybe will return Just False only when- -- we're sure the type is unlifted. | otherwise = dmds
compiler/GHC/Core/Opt/SpecConstr.hs view
@@ -30,7 +30,7 @@ import GHC.Core.Unfold import GHC.Core.FVs ( exprsFreeVarsList ) import GHC.Core.Opt.Monad-import GHC.Core.Opt.WorkWrap.Utils ( isWorkerSmallEnough, mkWorkerArgs )+import GHC.Core.Opt.WorkWrap.Utils import GHC.Core.DataCon import GHC.Core.Coercion hiding( substCo ) import GHC.Core.Rules@@ -1650,7 +1650,14 @@ = -- pprTrace "specialise bot" (ppr fn) $ return (nullUsage, spec_info) - | not (isNeverActive (idInlineActivation fn)) -- See Note [Transfer activation]+ | not (isNeverActive (idInlineActivation fn))+ -- See Note [Transfer activation]+ --+ --+ -- Don't specialise OPAQUE things, see Note [OPAQUE pragma].+ -- Since OPAQUE things are always never-active (see+ -- GHC.Parser.PostProcess.mkOpaquePragma) this guard never fires for+ -- OPAQUE things. , not (null arg_bndrs) -- Only specialise functions , Just all_calls <- lookupVarEnv bind_calls fn -- Some calls to it = -- pprTrace "specialise entry {" (ppr fn <+> ppr all_calls) $@@ -1771,20 +1778,25 @@ -- And build the results ; let spec_body_ty = exprType spec_body- (spec_lam_args1, spec_sig, spec_arity, spec_join_arity)+ (spec_lam_args1, spec_sig, spec_arity1, spec_join_arity1) = calcSpecInfo fn call_pat extra_bndrs -- Annotate the variables with the strictness information from -- the function (see Note [Strictness information in worker binders]) - (spec_lam_args, spec_call_args,_) = mkWorkerArgs fn False- spec_lam_args1 []- spec_body_ty- -- mkWorkerArgs: usual w/w hack to avoid generating- -- a spec_rhs of unlifted type and no args.- -- Unlike W/W we don't turn functions into strict workers- -- immediately here instead letting tidy handle this.- -- For this reason we can ignore the cbv marks.- -- See Note [Strict Worker Ids]. See Note [Tag Inference].+ (spec_lam_args, spec_call_args, spec_arity, spec_join_arity)+ | needsVoidWorkerArg fn arg_bndrs spec_lam_args1+ , (spec_lam_args, spec_call_args, _) <- addVoidWorkerArg spec_lam_args1 []+ -- needsVoidWorkerArg: usual w/w hack to avoid generating+ -- a spec_rhs of unlifted type and no args.+ -- Unlike W/W we don't turn functions into strict workers+ -- immediately here instead letting tidy handle this.+ -- For this reason we can ignore the cbv marks.+ -- See Note [Strict Worker Ids]. See Note [Tag Inference].+ , !spec_arity <- spec_arity1 + 1+ , !spec_join_arity <- fmap (+ 1) spec_join_arity1+ = (spec_lam_args, spec_call_args, spec_arity, spec_join_arity)+ | otherwise+ = (spec_lam_args1, spec_lam_args1, spec_arity1, spec_join_arity1) spec_id = mkLocalId spec_name Many (mkLamTypes spec_lam_args spec_body_ty)@@ -2442,7 +2454,7 @@ setStrUnfolding :: Id -> StrictnessMark -> Id -- setStrUnfolding id str = id setStrUnfolding id str- -- | pprTrace "setStrUnfolding"+ -- pprTrace "setStrUnfolding" -- (ppr id <+> ppr (isMarkedCbv str) $$ -- ppr (idType id) $$ -- text "boxed:" <> ppr (isBoxedType (idType id)) $$@@ -2453,7 +2465,7 @@ | not (isId id) || isEvaldUnfolding (idUnfolding id) = id | isMarkedStrict str- , not (isUnliftedType (idType id)) -- Pointless to stick an evald unfolding on unlifted types+ , not $ isUnliftedType (idType id) -- Pointless to stick an evald unfolding on unlifted types = -- trace "setStrUnfolding2" $ assert (isId id) $ assert (not $ hasCoreUnfolding $ idUnfolding id) $
compiler/GHC/Core/Opt/Specialise.hs view
@@ -1431,6 +1431,11 @@ && not (isNeverActive (idInlineActivation fn)) -- Don't specialise NOINLINE things -- See Note [Auto-specialisation and RULES]+ --+ -- Don't specialise OPAQUE things, see Note [OPAQUE pragma].+ -- Since OPAQUE things are always never-active (see+ -- GHC.Parser.PostProcess.mkOpaquePragma) this guard never fires for+ -- OPAQUE things. -- && not (certainlyWillInline (idUnfolding fn)) -- And it's not small -- See Note [Inline specialisations] for why we do not@@ -1519,7 +1524,7 @@ -- Maybe add a void arg to the specialised function, -- to avoid unlifted bindings -- See Note [Specialisations Must Be Lifted]- -- C.f. GHC.Core.Opt.WorkWrap.Utils.mkWorkerArgs+ -- C.f. GHC.Core.Opt.WorkWrap.Utils.needsVoidWorkerArg add_void_arg = isUnliftedType spec_fn_ty1 && not (isJoinId fn) (spec_bndrs, spec_rhs, spec_fn_ty) | add_void_arg = ( voidPrimId : spec_bndrs1
compiler/GHC/Core/Opt/WorkWrap.hs view
@@ -534,9 +534,6 @@ -- if two, then a worker and a -- wrapper. tryWW ww_opts is_rec fn_id rhs- -- Do this even if there is a NOINLINE pragma- -- See Note [Worker/wrapper for NOINLINE functions]- -- See Note [Drop absent bindings] | isAbsDmd (demandInfo fn_info) , not (isJoinId fn_id)@@ -551,6 +548,35 @@ | isRecordSelector fn_id = return [ (new_fn_id, rhs ) ] + -- Don't w/w OPAQUE things+ -- See Note [OPAQUE pragma]+ --+ -- Whilst this check might seem superfluous, since we strip boxity+ -- information in GHC.Core.Opt.DmdAnal.finaliseArgBoxities and+ -- CPR information in GHC.Core.Opt.CprAnal.cprAnalBind, it actually+ -- isn't. That is because we would still perform w/w when:+ --+ -- - An argument is used strictly, and -fworker-wrapper-cbv is+ -- enabled, or,+ -- - When demand analysis marks an argument as absent.+ --+ -- In a debug build we do assert that boxity and CPR information+ -- are actually stripped, since we want to prevent callers of OPAQUE+ -- things to do reboxing. See:+ -- - Note [The OPAQUE pragma and avoiding the reboxing of arguments]+ -- - Note [The OPAQUE pragma and avoiding the reboxing of results]+ | isOpaquePragma (inlinePragInfo fn_info)+ = assertPpr (onlyBoxedArguments (dmdSigInfo fn_info) &&+ isTopCprSig (cprSigInfo fn_info))+ (text "OPAQUE fun with boxity" $$+ ppr new_fn_id $$+ ppr (dmdSigInfo fn_info) $$+ ppr (cprSigInfo fn_info) $$+ ppr rhs) $+ return [ (new_fn_id, rhs) ]++ -- Do this even if there is a NOINLINE pragma+ -- See Note [Worker/wrapper for NOINLINE functions] | is_fun = splitFun ww_opts new_fn_id rhs @@ -899,18 +925,6 @@ The demand on the worker is then calculated using mkWorkerDemand, and always of the form [Demand=<L,1*(C1(...(C1(U))))>]---Note [Do not split void functions]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider this rather common form of binding:- $j = \x:Void# -> ...no use of x...--Since x is not used it'll be marked as absent. But there is no point-in w/w-ing because we'll simply add (\y:Void#), see GHC.Core.Opt.WorkWrap.Utils.mkWorerArgs.--If x has a more interesting type (eg Int, or Int#), there *is* a point-in w/w so that we don't pass the argument at all. Note [Thunk splitting] ~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/Core/Opt/WorkWrap/Utils.hs view
@@ -8,7 +8,8 @@ {-# LANGUAGE ViewPatterns #-} module GHC.Core.Opt.WorkWrap.Utils- ( WwOpts(..), initWwOpts, mkWwBodies, mkWWstr, mkWWstr_one, mkWorkerArgs+ ( WwOpts(..), initWwOpts, mkWwBodies, mkWWstr, mkWWstr_one+ , needsVoidWorkerArg, addVoidWorkerArg , DataConPatContext(..) , UnboxingDecision(..), wantToUnboxArg , findTypeShape, IsRecDataConResult(..), isRecDataCon@@ -34,6 +35,7 @@ import GHC.Core.Reduction import GHC.Core.FamInstEnv import GHC.Core.TyCon+import GHC.Core.TyCon.Set import GHC.Core.TyCon.RecWalk import GHC.Core.SimpleOpt( SimpleOpts ) @@ -48,7 +50,6 @@ import GHC.Types.Name ( getOccFS ) import GHC.Data.FastString-import GHC.Data.Maybe import GHC.Data.OrdList import GHC.Data.List.SetOps @@ -141,7 +142,6 @@ { wo_fam_envs :: !FamInstEnvs , wo_simple_opts :: !SimpleOpts , wo_cpr_anal :: !Bool- , wo_fun_to_thunk :: !Bool -- Used for absent argument error message , wo_module :: !Module@@ -155,7 +155,6 @@ { wo_fam_envs = fam_envs , wo_simple_opts = initSimpleOpts dflags , wo_cpr_anal = gopt Opt_CprAnal dflags- , wo_fun_to_thunk = gopt Opt_FunToThunk dflags , wo_module = this_mod , wo_unlift_strict = gopt Opt_WorkerWrapperUnlift dflags }@@ -240,11 +239,14 @@ ; let (work_args, work_marks) = unzip work_args_cbv -- Do CPR w/w. See Note [Always do CPR w/w]- ; (useful2, wrap_fn_cpr, work_fn_cpr, cpr_res_ty)+ ; (useful2, wrap_fn_cpr, work_fn_cpr) <- mkWWcpr_entry opts res_ty' res_cpr - ; let (work_lam_args, work_call_args, work_call_cbv) = mkWorkerArgs fun_id (wo_fun_to_thunk opts)- work_args work_marks cpr_res_ty+ ; let (work_lam_args, work_call_args, work_call_cbv)+ | needsVoidWorkerArg fun_id arg_vars work_args+ = addVoidWorkerArg work_args work_marks+ | otherwise+ = (work_args, work_args, work_marks) call_work work_fn = mkVarApps (Var work_fn) work_call_args call_rhs fn_rhs = mkAppsBeta fn_rhs fn_args@@ -347,10 +349,20 @@ of the fun body in the next run of the Simplifier, but CoreLint will complain in the meantime, so zap it. -We zap in mkWwBodies because we need the zapped variables both when binding them-in mkWWstr (mkAbsentFiller, specifically) and in mkWorkerArgs, where we produce-the call to the fun body.+We zap in mkWwBodies because we need the zapped variables when binding them in+mkWWstr (mkAbsentFiller, specifically). +Note [Do not split void functions]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider this rather common form of binding:+ $j = \x:Void# -> ...no use of x...++Since x is not used it'll be marked as absent. But there is no point+in w/w-ing because we'll simply add (\y:Void#), see addVoidWorkerArg.++If x has a more interesting type (eg Int, or Int#), there *is* a point+in w/w so that we don't pass the argument at all.+ ************************************************************************ * * \subsection{Making wrapper args}@@ -369,44 +381,29 @@ We use the state-token type which generates no code. -} --- | Prevent a function from becoming a thunk by adding a void argument if--- required.-mkWorkerArgs :: Id -- The wrapper Id- -> Bool -- Allow fun->thunk conversion.- -> [Var]- -> [CbvMark]- -> Type -- Type of body- -> ([Var], -- Lambda bound args- [Var], -- Args at call site- [CbvMark] -- cbv semantics for the worker args.- )-mkWorkerArgs wrap_id fun_to_thunk args cbv_marks res_ty- | not (isJoinId wrap_id) -- Join Ids never need an extra arg- , not (any isId args) -- No existing value lambdas- , needs_a_value_lambda -- and we need to add one- = (args ++ [voidArgId], args ++ [voidPrimId], cbv_marks ++ [NotMarkedCbv])-- | otherwise- = (args, args, cbv_marks)- where- -- If fun_to_thunk is False we always keep at least one value- -- argument: see Note [Protecting the last value argument]- -- If it is True, we only need to keep a value argument if- -- the result type is (or might be) unlifted, in which case- -- dropping the last arg would mean we wrongly used call-by-value- needs_a_value_lambda- = not fun_to_thunk- || might_be_unlifted+-- | Whether the worker needs an additional `Void#` arg as per+-- Note [Protecting the last value argument] or+-- Note [Preserving float barriers].+needsVoidWorkerArg :: Id -> [Var] -> [Var] -> Bool+needsVoidWorkerArg fn_id wrap_args work_args+ = not (isJoinId fn_id) && no_value_arg -- See Note [Protecting the last value argument]+ || needs_float_barrier -- See Note [Preserving float barriers]+ where+ no_value_arg = all (not . isId) work_args+ is_float_barrier v = isId v && hasNoOneShotInfo (idOneShotInfo v)+ wrap_had_barrier = any is_float_barrier wrap_args+ work_has_barrier = any is_float_barrier work_args+ needs_float_barrier = wrap_had_barrier && not work_has_barrier - -- Might the result be lifted?- -- False => definitely lifted- -- True => might be unlifted- -- We may encounter a representation-polymorphic result, in which case we- -- conservatively assume that we have laziness that needs- -- preservation. See #15186.- might_be_unlifted = case isLiftedType_maybe res_ty of- Just lifted -> not lifted- Nothing -> True+-- | Inserts a `Void#` arg before the first value argument (but after leading type args).+addVoidWorkerArg :: [Var] -> [CbvMark]+ -> ([Var], -- Lambda bound args+ [Var], -- Args at call site+ [CbvMark]) -- cbv semantics for the worker args.+addVoidWorkerArg work_args cbv_marks+ = (ty_args ++ voidArgId:rest, ty_args ++ voidPrimId:rest, NotMarkedCbv:cbv_marks)+ where+ (ty_args, rest) = break isId work_args {- Note [Protecting the last value argument]@@ -414,14 +411,72 @@ If the user writes (\_ -> E), they might be intentionally disallowing the sharing of E. Since absence analysis and worker-wrapper are keen to remove such unused arguments, we add in a void argument to prevent-the function from becoming a thunk.+the function from becoming a thunk. Three reasons why turning a function+into a thunk might be bad: -The user can avoid adding the void argument with the -ffun-to-thunk-flag. However, this can create sharing, which may be bad in two ways. 1) It can-create a space leak. 2) It can prevent inlining *under a lambda*. If w/w-removes the last argument from a function f, then f now looks like a thunk, and-so f can't be inlined *under a lambda*.+1) It can create a space leak. e.g.+ f x = let y () = [1..x]+ in (sum (y ()) + length (y ()))+ As written it'll calculate [1..x] twice, and avoid keeping a big+ list around. (Of course let-floating may introduce the leak; but+ at least w/w doesn't.) +2) It can prevent inlining *under a lambda*. e.g.+ g = \y. [1..100]+ f = \t. g ()+ Here we can inline g under the \t. But we won't if we remove the \y.++3) It can create an unlifted binding. E.g.+ g :: Int -> Int#+ g = \x. 30#+ Removing the \x would leave an unlifted binding.++NB: none of these apply to a join point.++Note [Preserving float barriers]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider+```+let+ t = sum [0..x]+ f a{os} b[Dmd=A] c{os} = ... t ...+in f 1 2 3 + f 4 5 6+```+Here, we would like to drop the argument `b` because it's absent. But doing so+leaves behind only one-shot lambdas, `$wf a{os} c{os} = ...`, and then the+Simplifier will inline `t` into `$wf`, because `$wf` says "I'm only called+once". That's bad, because we lost sharing of `t`! Similarly, FloatIn would+happily float `t` into `$wf`, see Note [Floating in past a lambda group].++Why does floating happen after dropping `b` but not before? Because `b` was the+only non-one-shot value lambda left, acting as our "float barrier".++Definition: A float barrier is a non-one-shot value lambda.+Key insight: If `f` had a float barrier, `$wf` has to have one, too.++To this end, in `needsVoidWorkerArg`, we check whether the wrapper had a float+barrier and if the worker has none so far. If that is the case, we add a `Void#`+argument at the end as an artificial float barrier.++The issue is tracked in #21150. It came up when compiling GHC itself, in+GHC.Tc.Gen.Bind.mkEdges. There the key_map thunk was inlined after WW dropped a+leading absent non-one-shot arg. Here are some example wrapper arguments of+which some are absent or one-shot and the resulting worker arguments:++ * \a{Abs}.\b{os}.\c{os}... ==> \b{os}.\c{os}.\(_::Void#)...+ Wrapper arg `a` was the only float barrier and had been dropped. Hence Void#+ * \a{Abs,os}.\b{os}.\c... ==> \b{os}.\c...+ Worker arg `c` is a float barrier.+ * \a.\b{Abs}.\c{os}... ==> \a.\c{os}...+ Worker arg `a` is a float barrier.+ * \a{os}.\b{Abs,os}.\c{os}... ==> \a{os}.\c{os}...+ Wrapper didn't have a float barrier, no need for Void#.+ * \a{Abs,os}.... ==> ... (no value lambda left)+ This examples simply demonstrates that preserving float barriers is not+ enough to subsume Note [Protecting the last value argument].++Executable examples in T21150.+ Note [Join points and beta-redexes] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Originally, the worker would invoke the original function by calling it with@@ -575,6 +630,7 @@ , isStrUsedDmd dmd , not (isFunTy ty) , not (isUnliftedType ty) -- Already unlifted!+ -- NB: function arguments have a fixed RuntimeRep, so it's OK to call isUnliftedType here = Unlift | otherwise@@ -605,7 +661,7 @@ = StopUnboxing where- -- | See Note [non-algebraic or open body type warning]+ -- See Note [non-algebraic or open body type warning] open_body_ty_warning = warnPprTrace True "wantToUnboxResult: non-algebraic or open body type" (ppr ty) Nothing isLinear :: Scaled a -> Bool@@ -621,6 +677,7 @@ 1. A strict data type argument, that * is an algebraic data type (not a newtype)+ * is not recursive (as per 'isRecDataCon') * has a single constructor (thus is a "product") * that may bind existentials We can transform@@ -632,6 +689,7 @@ 2. The constructed result of a function, if * its type is an algebraic data type (not a newtype)+ * is not recursive (as per 'isRecDataCon') * (might have multiple constructors, in contrast to (1)) * the applied data constructor *does not* bind existentials We can transform@@ -860,7 +918,7 @@ mkAbsentFiller opts arg -- The lifted case: Bind 'absentError' for a nice panic message if we are -- wrong (like we were in #11126). See (1) in Note [Absent fillers]- | not (isUnliftedType arg_ty)+ | mightBeLiftedType arg_ty , not is_strict, not is_evald -- See (2) in Note [Absent fillers] = Just (mkAbsentErrorApp arg_ty msg) @@ -1189,15 +1247,17 @@ -- | @isRecDataCon _ fuel dc@, where @tc = dataConTyCon dc@ returns ----- * @Just Recursive@ if the analysis found that @tc@ is reachable through one--- of @dc@'s fields--- * @Just NonRecursive@ if the analysis found that @tc@ is not reachable--- through one of @dc@'s fields--- * @Nothing@ is returned in two cases. The first is when @fuel /= Infinity@--- and @f@ expansions of nested data TyCons were not enough to prove+-- * @DefinitelyRecursive@ if the analysis found that @tc@ is reachable+-- through one of @dc@'s @arg_tys@.+-- * @NonRecursiveOrUnsure@ if the analysis found that @tc@ is not reachable+-- through one of @dc@'s fields (so surely non-recursive).+-- * @NonRecursiveOrUnsure@ when @fuel /= Infinity@+-- and @fuel@ expansions of nested data TyCons were not enough to prove -- non-recursivenss, nor arrive at an occurrence of @tc@ thus proving--- recursiveness. The other is when we hit an abstract TyCon (one without+-- recursiveness. (So not sure if non-recursive.)+-- * @NonRecursiveOrUnsure@ when we hit an abstract TyCon (one without -- visible DataCons), such as those imported from .hs-boot files.+-- Similarly for stuck type and data families. -- -- If @fuel = 'Infinity'@ and there are no boot files involved, then the result -- is never @Nothing@ and the analysis is a depth-first search. If @fuel = 'Int'@@ -1207,84 +1267,64 @@ -- See Note [Detecting recursive data constructors] for which recursive DataCons -- we want to flag. isRecDataCon :: FamInstEnvs -> IntWithInf -> DataCon -> IsRecDataConResult-isRecDataCon fam_envs fuel dc- | isTupleDataCon dc || isUnboxedSumDataCon dc+isRecDataCon fam_envs fuel orig_dc+ | isTupleDataCon orig_dc || isUnboxedSumDataCon orig_dc = NonRecursiveOrUnsure | otherwise- = -- pprTrace "isRecDataCon" (ppr dc <+> dcolon <+> ppr (dataConRepType dc) $$ ppr fuel $$ ppr answer)- answer+ = -- pprTraceWith "isRecDataCon" (\answer -> ppr dc <+> dcolon <+> ppr (dataConRepType dc) $$ ppr fuel $$ ppr answer) $+ go_dc fuel emptyTyConSet orig_dc where- answer = go_dc fuel (setRecTcMaxBound 1 initRecTc) dc- (<||>) = combineIRDCR-- go_dc :: IntWithInf -> RecTcChecker -> DataCon -> IsRecDataConResult- go_dc fuel rec_tc dc =- combineIRDCRs [ go_arg_ty fuel rec_tc (scaledThing arg_ty)- | arg_ty <- dataConRepArgTys dc ]+ go_dc :: IntWithInf -> TyConSet -> DataCon -> IsRecDataConResult+ go_dc fuel visited_tcs dc =+ combineIRDCRs [ go_arg_ty fuel visited_tcs arg_ty+ | arg_ty <- map scaledThing (dataConRepArgTys dc) ] - go_arg_ty :: IntWithInf -> RecTcChecker -> Type -> IsRecDataConResult- go_arg_ty fuel rec_tc ty+ go_arg_ty :: IntWithInf -> TyConSet -> Type -> IsRecDataConResult+ go_arg_ty fuel visited_tcs ty --- | pprTrace "arg_ty" (ppr ty) False = undefined - | Just (_, _arg_ty, _res_ty) <- splitFunTy_maybe ty- -- = go_arg_ty fuel rec_tc _arg_ty <||> go_arg_ty fuel rec_tc _res_ty- -- Plausible, but unnecessary for CPR.- -- See Note [Detecting recursive data constructors], point (1)- = NonRecursiveOrUnsure- | Just (_tcv, ty') <- splitForAllTyCoVar_maybe ty- = go_arg_ty fuel rec_tc ty'- -- See Note [Detecting recursive data constructors], point (2)+ = go_arg_ty fuel visited_tcs ty'+ -- See Note [Detecting recursive data constructors], point (A) | Just (tc, tc_args) <- splitTyConApp_maybe ty- = combineIRDCRs (map (go_arg_ty fuel rec_tc) tc_args)- <||> go_tc_app fuel rec_tc tc tc_args+ = go_tc_app fuel visited_tcs tc tc_args | otherwise = NonRecursiveOrUnsure - -- | PRECONDITION: tc_args has no recursive occs- -- See Note [Detecting recursive data constructors], point (5)- go_tc_app :: IntWithInf -> RecTcChecker -> TyCon -> [Type] -> IsRecDataConResult- go_tc_app fuel rec_tc tc tc_args+ go_tc_app :: IntWithInf -> TyConSet -> TyCon -> [Type] -> IsRecDataConResult+ go_tc_app fuel visited_tcs tc tc_args =+ case tyConDataCons_maybe tc of --- | pprTrace "tc_app" (vcat [ppr tc, ppr tc_args]) False = undefined-- | tc == dataConTyCon dc- = DefinitelyRecursive -- loop found!-- | isPrimTyCon tc- = NonRecursiveOrUnsure-- | not $ tcIsRuntimeTypeKind $ tyConResKind tc- = NonRecursiveOrUnsure-- | isAbstractTyCon tc -- When tc has no DataCons, from an hs-boot file- = NonRecursiveOrUnsure -- See Note [Detecting recursive data constructors], point (7)-- | isFamilyTyCon tc- -- This is the only place where we look at tc_args- -- See Note [Detecting recursive data constructors], point (5)- = case topReduceTyFamApp_maybe fam_envs tc tc_args of- Just (HetReduction (Reduction _ rhs) _) -> go_arg_ty fuel rec_tc rhs- Nothing -> DefinitelyRecursive -- we hit this case for 'Any'+ _ | Just (HetReduction (Reduction _ rhs) _) <- topReduceTyFamApp_maybe fam_envs tc tc_args+ -- This is the only place where we look at tc_args, which might have+ -- See Note [Detecting recursive data constructors], point (C) and (5)+ -> go_arg_ty fuel visited_tcs rhs - | otherwise- = assertPpr (isAlgTyCon tc) (ppr tc <+> ppr dc) $- case checkRecTc rec_tc tc of- Nothing -> NonRecursiveOrUnsure- -- we expanded this TyCon once already, no need to test it multiple times+ _ | tc == dataConTyCon orig_dc+ -> DefinitelyRecursive -- loop found! - Just rec_tc'- | Just (_tvs, rhs, _co) <- unwrapNewTyCon_maybe tc- -- See Note [Detecting recursive data constructors], points (2) and (3)- -> go_arg_ty fuel rec_tc' rhs+ Just dcs+ | DefinitelyRecursive <- combineIRDCRs [ go_arg_ty fuel visited_tcs' ty | ty <- tc_args ]+ -- Check tc_args, See Note [Detecting recursive data constructors], point (5)+ -- The new visited_tcs', so that we don't recursively check tc,+ -- promising that we will check it below.+ -- Do the tc_args check *before* the dcs check below, otherwise+ -- we might miss an obvious rec occ in tc_args when we run out of+ -- fuel and respond NonRecursiveOrUnsure instead+ -> DefinitelyRecursive - | fuel < 0- -> NonRecursiveOrUnsure -- that's why we track fuel!+ | fuel >= 0+ -- See Note [Detecting recursive data constructors], point (4)+ , not (tc `elemTyConSet` visited_tcs)+ -- only need to check tc if we haven't visited it already. NB: original visited_tcs+ -> combineIRDCRs [ go_dc (subWithInf fuel 1) visited_tcs' dc | dc <- dcs ]+ -- Finally: check ds - | let dcs = expectJust "isRecDataCon:go_tc_app" $ tyConDataCons_maybe tc- -> combineIRDCRs (map (\dc -> go_dc (subWithInf fuel 1) rec_tc' dc) dcs)- -- See Note [Detecting recursive data constructors], point (4)+ _ -> NonRecursiveOrUnsure+ where+ visited_tcs' = extendTyConSet visited_tcs tc {- ************************************************************************@@ -1301,12 +1341,10 @@ -> Cpr -- CPR analysis results -> UniqSM (Bool, -- Is w/w'ing useful? CoreExpr -> CoreExpr, -- New wrapper. 'nop_fn' if not useful- CoreExpr -> CoreExpr, -- New worker. 'nop_fn' if not useful- Type) -- Type of worker's body.- -- Just the input body_ty if not useful+ CoreExpr -> CoreExpr) -- New worker. 'nop_fn' if not useful -- ^ Entrypoint to CPR W/W. See Note [Worker/wrapper for CPR] for an overview. mkWWcpr_entry opts body_ty body_cpr- | not (wo_cpr_anal opts) = return (badWorker, nop_fn, nop_fn, body_ty)+ | not (wo_cpr_anal opts) = return (badWorker, nop_fn, nop_fn) | otherwise = do -- Part (1) res_bndr <- mk_res_bndr body_ty@@ -1322,10 +1360,9 @@ -- Stacking unboxer (work_fn) and builder (wrap_fn) together let wrap_fn = unbox_transit_tup rebuilt_result -- 3 2 work_fn body = bind_res_bndr body (work_unpack_res transit_tup) -- 1 2 3- work_body_ty = exprType transit_tup return $ if not useful- then (badWorker, nop_fn, nop_fn, body_ty)- else (goodWorker, wrap_fn, work_fn, work_body_ty)+ then (badWorker, nop_fn, nop_fn)+ else (goodWorker, wrap_fn, work_fn) -- | Part (1) of Note [Worker/wrapper for CPR]. mk_res_bndr :: Type -> UniqSM Id
compiler/GHC/CoreToStg.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE TypeFamilies #-}@@ -455,7 +456,7 @@ ; alts2 <- extendVarEnvCts [(bndr, LambdaBound)] (mapM vars_alt alts) ; return (StgCase scrut2 bndr (mkStgAltType bndr alts) alts2) } where- vars_alt :: CoreAlt -> CtsM (AltCon, [Var], StgExpr)+ vars_alt :: CoreAlt -> CtsM StgAlt vars_alt (Alt con binders rhs) | DataAlt c <- con, c == unboxedUnitDataCon = -- This case is a bit smelly.@@ -463,14 +464,18 @@ -- where a nullary tuple is mapped to (State# World#) assert (null binders) $ do { rhs2 <- coreToStgExpr rhs- ; return (DEFAULT, [], rhs2) }+ ; return GenStgAlt{alt_con=DEFAULT,alt_bndrs=mempty,alt_rhs=rhs2}+ } | otherwise = let -- Remove type variables binders' = filterStgBinders binders in extendVarEnvCts [(b, LambdaBound) | b <- binders'] $ do rhs2 <- coreToStgExpr rhs- return (con, binders', rhs2)+ return $! GenStgAlt{ alt_con = con+ , alt_bndrs = binders'+ , alt_rhs = rhs2+ } coreToStgExpr (Let bind body) = coreToStgLet bind body coreToStgExpr e = pprPanic "coreToStgExpr" (ppr e)
compiler/GHC/CoreToStg/Prep.hs view
@@ -1054,9 +1054,9 @@ (Var f) args | Just KeepAliveOp <- isPrimOpId_maybe f- , CpeApp (Type arg_rep)- : CpeApp (Type arg_ty)+ , CpeApp (Type arg_lev) : CpeApp (Type _result_rep)+ : CpeApp (Type arg_ty) : CpeApp (Type result_ty) : CpeApp arg : CpeApp s0@@ -1070,13 +1070,14 @@ _ -> cpe_app env k (CpeApp s0 : rest) ; let touchId = primOpId TouchOp expr = Case k' y result_ty [Alt DEFAULT [] rhs]- rhs = let scrut = mkApps (Var touchId) [Type arg_rep, Type arg_ty, arg, Var realWorldPrimId]+ rhs = let scrut = mkApps (Var touchId) [Type arg_lev, Type arg_ty, arg, Var realWorldPrimId] in Case scrut s2 result_ty [Alt DEFAULT [] (Var y)] ; (floats', expr') <- cpeBody env expr ; return (floats `appendFloats` floats', expr') } | Just KeepAliveOp <- isPrimOpId_maybe f- = panic "invalid keepAlive# application"+ = pprPanic "invalid keepAlive# application" $+ vcat [ text "args:" <+> ppr args ] -- runRW# magic cpe_app env (Var f) (CpeApp _runtimeRep@Type{} : CpeApp _type@Type{} : CpeApp arg : rest)@@ -1135,7 +1136,7 @@ ; (app, floats,unsat_ticks) <- rebuild_app env args fun' fun_floats [] Nothing ; mb_saturate Nothing app floats unsat_ticks (val_args args) } - -- | Count the number of value arguments.+ -- Count the number of value arguments. val_args :: [ArgInfo] -> Int val_args args = go args 0 where@@ -1651,16 +1652,7 @@ ok bndr (Var arg) = bndr == arg ok _ _ = False - -- We can't eta reduce something which must be saturated.- ok_to_eta_reduce (Var f) = not (hasNoBinding f) &&- not (isLinearType (idType f)) && -- Unsure why this is unsafe.- (not (isJoinId f) || idJoinArity f <= n_remaining) &&- -- Don't undersaturate join points.- -- See Note [Invariants on join points] in GHC.Core, and #20599- (idCbvMarkArity f <= n_remaining_vals)- -- Similar for StrictWorkerIds. See Note [Strict Worker Ids]--+ ok_to_eta_reduce (Var f) = canEtaReduceToArity f n_remaining n_remaining_vals ok_to_eta_reduce _ = False -- Safe. ToDo: generalise
compiler/GHC/Data/Graph/Color.hs view
@@ -268,9 +268,9 @@ assignColors colors graph ks = assignColors' colors graph [] ks - where assignColors' :: UniqFM cls (UniqSet color) -- ^ map of (node class -> set of colors available for this class).- -> Graph k cls color -- ^ the graph- -> [k] -- ^ nodes to assign a color to.+ where assignColors' :: UniqFM cls (UniqSet color) -- map of (node class -> set of colors available for this class).+ -> Graph k cls color -- the graph+ -> [k] -- nodes to assign a color to. -> [k] -> ( Graph k cls color -- the colored graph , [k])@@ -303,9 +303,9 @@ selectColor :: ( Uniquable k, Uniquable cls, Uniquable color , Outputable cls)- => UniqFM cls (UniqSet color) -- ^ map of (node class -> set of colors available for this class).- -> Graph k cls color -- ^ the graph- -> k -- ^ key of the node to select a color for.+ => UniqFM cls (UniqSet color) -- map of (node class -> set of colors available for this class).+ -> Graph k cls color -- the graph+ -> k -- key of the node to select a color for. -> Maybe color selectColor colors graph u
compiler/GHC/Driver/Backpack.hs view
@@ -920,7 +920,12 @@ -- Now, what are the dependencies. let inst_nodes = map NodeKey_Unit inst_deps- mod_nodes = [k | (_, mnwib) <- msDeps ms, let k = NodeKey_Module (ModNodeKeyWithUid (fmap unLoc mnwib) (moduleUnitId this_mod)), k `elem` home_keys]+ mod_nodes =+ -- hs-boot edge+ [k | k <- [NodeKey_Module (ModNodeKeyWithUid (GWIB (ms_mod_name ms) IsBoot) (moduleUnitId this_mod))], NotBoot == isBootSummary ms, k `elem` home_keys ] +++ -- Normal edges+ [k | (_, mnwib) <- msDeps ms, let k = NodeKey_Module (ModNodeKeyWithUid (fmap unLoc mnwib) (moduleUnitId this_mod)), k `elem` home_keys]+ return (ModuleNode (mod_nodes ++ inst_nodes) ms)
compiler/GHC/Driver/CodeOutput.hs view
@@ -4,7 +4,7 @@ \section{Code output phase} -} -+{-# LANGUAGE ScopedTypeVariables #-} module GHC.Driver.CodeOutput ( codeOutput@@ -23,7 +23,7 @@ import GHC.CmmToC ( cmmToC ) import GHC.Cmm.Lint ( cmmLint )-import GHC.Cmm ( RawCmmGroup )+import GHC.Cmm import GHC.Cmm.CLabel import GHC.Driver.Session@@ -70,7 +70,8 @@ -} codeOutput- :: Logger+ :: forall a.+ Logger -> TmpFs -> DynFlags -> UnitState@@ -110,18 +111,39 @@ ; return cmm } - ; a <- case backend dflags of+ ; let final_stream :: Stream IO RawCmmGroup (ForeignStubs, a)+ final_stream = do+ { a <- linted_cmm_stream+ ; let stubs = genForeignStubs a+ ; emitInitializerDecls this_mod stubs+ ; return (stubs, a) }++ ; (stubs, a) <- case backend dflags of NCG -> outputAsm logger dflags this_mod location filenm- linted_cmm_stream- ViaC -> outputC logger dflags filenm linted_cmm_stream pkg_deps- LLVM -> outputLlvm logger dflags filenm linted_cmm_stream+ final_stream+ ViaC -> outputC logger dflags filenm final_stream pkg_deps+ LLVM -> outputLlvm logger dflags filenm final_stream Interpreter -> panic "codeOutput: Interpreter" NoBackend -> panic "codeOutput: NoBackend"- ; let stubs = genForeignStubs a ; stubs_exist <- outputForeignStubs logger tmpfs dflags unit_state this_mod location stubs ; return (filenm, stubs_exist, foreign_fps, a) } +-- | See Note [Initializers and finalizers in Cmm] in GHC.Cmm.InitFini for details.+emitInitializerDecls :: Module -> ForeignStubs -> Stream IO RawCmmGroup ()+emitInitializerDecls this_mod (ForeignStubs _ cstub)+ | initializers <- getInitializers cstub+ , not $ null initializers =+ let init_array = CmmData sect statics+ lbl = mkInitializerArrayLabel this_mod+ sect = Section InitArray lbl+ statics = CmmStaticsRaw lbl+ [ CmmStaticLit $ CmmLabel fn_name+ | fn_name <- initializers+ ]+ in Stream.yield [init_array]+emitInitializerDecls _ _ = return ()+ doOutput :: String -> (Handle -> IO a) -> IO a doOutput filenm io_action = bracket (openFile filenm WriteMode) hClose io_action @@ -221,7 +243,7 @@ NoStubs -> return (False, Nothing) - ForeignStubs (CHeader h_code) (CStub c_code) -> do+ ForeignStubs (CHeader h_code) (CStub c_code _ _) -> do let stub_c_output_d = pprCode CStyle c_code stub_c_output_w = showSDoc dflags stub_c_output_d@@ -298,20 +320,18 @@ -- | Generate code to initialise cost centres profilingInitCode :: Platform -> Module -> CollectedCCs -> CStub profilingInitCode platform this_mod (local_CCs, singleton_CCSs)- = CStub $ vcat- $ map emit_cc_decl local_CCs- ++ map emit_ccs_decl singleton_CCSs- ++ [emit_cc_list local_CCs]- ++ [emit_ccs_list singleton_CCSs]- ++ [ text "static void prof_init_" <> ppr this_mod- <> text "(void) __attribute__((constructor));"- , text "static void prof_init_" <> ppr this_mod <> text "(void)"- , braces (vcat- [ text "registerCcList" <> parens local_cc_list_label <> semi- , text "registerCcsList" <> parens singleton_cc_list_label <> semi- ])- ]+ = initializerCStub platform fn_name decls body where+ fn_name = mkInitializerStubLabel this_mod "prof_init"+ decls = vcat+ $ map emit_cc_decl local_CCs+ ++ map emit_ccs_decl singleton_CCSs+ ++ [emit_cc_list local_CCs]+ ++ [emit_ccs_list singleton_CCSs]+ body = vcat+ [ text "registerCcList" <> parens local_cc_list_label <> semi+ , text "registerCcsList" <> parens singleton_cc_list_label <> semi+ ] emit_cc_decl cc = text "extern CostCentre" <+> cc_lbl <> text "[];" where cc_lbl = pdoc platform (mkCCLabel cc)@@ -343,19 +363,14 @@ -> [InfoProvEnt] -> CStub ipInitCode do_info_table platform this_mod ents- = if not do_info_table- then mempty- else CStub $ vcat- $ map emit_ipe_decl ents- ++ [emit_ipe_list ents]- ++ [ text "static void ip_init_" <> ppr this_mod- <> text "(void) __attribute__((constructor));"- , text "static void ip_init_" <> ppr this_mod <> text "(void)"- , braces (vcat- [ text "registerInfoProvList" <> parens local_ipe_list_label <> semi- ])- ]+ | not do_info_table = mempty+ | otherwise = initializerCStub platform fn_nm decls body where+ fn_nm = mkInitializerStubLabel this_mod "ip_init"+ decls = vcat+ $ map emit_ipe_decl ents+ ++ [emit_ipe_list ents]+ body = text "registerInfoProvList" <> parens local_ipe_list_label <> semi emit_ipe_decl ipe = text "extern InfoProvEnt" <+> ipe_lbl <> text "[];" where ipe_lbl = pprCLabel platform CStyle (mkIPELabel ipe)
compiler/GHC/Driver/Config/StgToCmm.hs view
@@ -22,7 +22,7 @@ , stgToCmmTmpDir = tmpDir dflags , stgToCmmContext = initSDocContext dflags defaultDumpStyle , stgToCmmDebugLevel = debugLevel dflags- , stgToCmmBinBlobThresh = binBlobThreshold dflags+ , stgToCmmBinBlobThresh = b_blob , stgToCmmMaxInlAllocSize = maxInlineAllocSize dflags -- ticky options , stgToCmmDoTicky = gopt Opt_Ticky dflags@@ -57,11 +57,13 @@ , stgToCmmAvx = isAvxEnabled dflags , stgToCmmAvx2 = isAvx2Enabled dflags , stgToCmmAvx512f = isAvx512fEnabled dflags+ , stgToCmmTickyAP = gopt Opt_Ticky_AP dflags } where profile = targetProfile dflags platform = profilePlatform profile bk_end = backend dflags ncg = bk_end == NCG llvm = bk_end == LLVM+ b_blob = if not ncg then Nothing else binBlobThreshold dflags x86ish = case platformArch platform of ArchX86 -> True ArchX86_64 -> True
+ compiler/GHC/Driver/Config/Tidy.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE LambdaCase #-}++module GHC.Driver.Config.Tidy+ ( initTidyOpts+ , initStaticPtrOpts+ )+where++import GHC.Prelude++import GHC.Iface.Tidy+import GHC.Iface.Tidy.StaticPtrTable++import GHC.Driver.Session+import GHC.Driver.Env+import GHC.Driver.Backend++import GHC.Core.Make (getMkStringIds)+import GHC.Data.Maybe+import GHC.Utils.Panic+import GHC.Utils.Outputable+import GHC.Builtin.Names+import GHC.Tc.Utils.Env (lookupGlobal_maybe)+import GHC.Types.TyThing+import GHC.Platform.Ways++import qualified GHC.LanguageExtensions as LangExt++initTidyOpts :: HscEnv -> IO TidyOpts+initTidyOpts hsc_env = do+ let dflags = hsc_dflags hsc_env+ static_ptr_opts <- if not (xopt LangExt.StaticPointers dflags)+ then pure Nothing+ else Just <$> initStaticPtrOpts hsc_env+ pure $ TidyOpts+ { opt_name_cache = hsc_NC hsc_env+ , opt_collect_ccs = ways dflags `hasWay` WayProf+ , opt_unfolding_opts = unfoldingOpts dflags+ , opt_expose_unfoldings = if | gopt Opt_OmitInterfacePragmas dflags -> ExposeNone+ | gopt Opt_ExposeAllUnfoldings dflags -> ExposeAll+ | otherwise -> ExposeSome+ , opt_expose_rules = not (gopt Opt_OmitInterfacePragmas dflags)+ , opt_trim_ids = gopt Opt_OmitInterfacePragmas dflags+ , opt_static_ptr_opts = static_ptr_opts+ }++initStaticPtrOpts :: HscEnv -> IO StaticPtrOpts+initStaticPtrOpts hsc_env = do+ let dflags = hsc_dflags hsc_env++ let lookupM n = lookupGlobal_maybe hsc_env n >>= \case+ Succeeded r -> pure r+ Failed err -> pprPanic "initStaticPtrOpts: couldn't find" (ppr (err,n))++ mk_string <- getMkStringIds (fmap tyThingId . lookupM)+ static_ptr_info_datacon <- tyThingDataCon <$> lookupM staticPtrInfoDataConName+ static_ptr_datacon <- tyThingDataCon <$> lookupM staticPtrDataConName++ pure $ StaticPtrOpts+ { opt_platform = targetPlatform dflags++ -- If we are compiling for the interpreter we will insert any necessary+ -- SPT entries dynamically, otherwise we add a C stub to do so+ , opt_gen_cstub = case backend dflags of+ Interpreter -> False+ _ -> True++ , opt_mk_string = mk_string+ , opt_static_ptr_info_datacon = static_ptr_info_datacon+ , opt_static_ptr_datacon = static_ptr_datacon+ }+
compiler/GHC/Driver/Main.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE NondecreasingIndentation #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE GADTs #-} {-# OPTIONS_GHC -fprof-auto-top #-}@@ -80,6 +79,9 @@ , hscParseExpr , hscParseType , hscCompileCoreExpr+ , hscTidy++ -- * Low-level exports for hooks , hscCompileCoreExpr' -- We want to make sure that we export enough to be able to redefine@@ -110,6 +112,7 @@ import GHC.Driver.Config.Stg.Pipeline (initStgPipelineOpts) import GHC.Driver.Config.StgToCmm (initStgToCmmConfig) import GHC.Driver.Config.Diagnostic+import GHC.Driver.Config.Tidy import GHC.Driver.Hooks import GHC.Runtime.Context@@ -143,14 +146,17 @@ import GHC.Core import GHC.Core.Tidy ( tidyExpr ) import GHC.Core.Type ( Type, Kind )-import GHC.Core.Lint ( lintInteractiveExpr )+import GHC.Core.Lint ( lintInteractiveExpr, endPassIO ) import GHC.Core.Multiplicity import GHC.Core.Utils ( exprType ) import GHC.Core.ConLike+import GHC.Core.Opt.Monad ( CoreToDo (..)) import GHC.Core.Opt.Pipeline import GHC.Core.TyCon import GHC.Core.InstEnv import GHC.Core.FamInstEnv+import GHC.Core.Rules+import GHC.Core.Stats import GHC.CoreToStg.Prep import GHC.CoreToStg ( coreToStg )@@ -444,8 +450,6 @@ PFailed pst -> handleWarningsThrowErrors (getPsMessages pst) POk pst rdr_module -> do- let (warns, errs) = getPsMessages pst- logDiagnostics (GhcPsMessage <$> warns) liftIO $ putDumpFileMaybe logger Opt_D_dump_parsed "Parser" FormatHaskell (ppr rdr_module) liftIO $ putDumpFileMaybe logger Opt_D_dump_parsed_ast "Parser AST"@@ -454,7 +458,6 @@ rdr_module) liftIO $ putDumpFileMaybe logger Opt_D_source_stats "Source Statistics" FormatText (ppSourceStats False rdr_module)- when (not $ isEmptyMessages errs) $ throwErrors (GhcPsMessage <$> errs) -- To get the list of extra source files, we take the list -- that the parser gave us,@@ -490,10 +493,16 @@ -- apply parse transformation of plugins let applyPluginAction p opts- = parsedResultAction p opts mod_summary+ = uncurry (parsedResultAction p opts mod_summary) hsc_env <- getHscEnv- withPlugins (hsc_plugins hsc_env) applyPluginAction res+ (transformed, (warns, errs)) <-+ withPlugins (hsc_plugins hsc_env) applyPluginAction (res, getPsMessages pst) + logDiagnostics (GhcPsMessage <$> warns)+ unless (isEmptyMessages errs) $ throwErrors (GhcPsMessage <$> errs)++ return transformed+ checkBidirectionFormatChars :: PsLoc -> StringBuffer -> Maybe (NonEmpty (PsLoc, Char, String)) checkBidirectionFormatChars start_loc sb | containsBidirectionalFormatChar sb = Just $ go start_loc sb@@ -941,8 +950,8 @@ plugins <- liftIO $ readIORef (tcg_th_coreplugins tc_result) simplified_guts <- hscSimplify' plugins desugared_guts - (cg_guts, details) <- {-# SCC "CoreTidy" #-}- liftIO $ tidyProgram hsc_env simplified_guts+ (cg_guts, details) <-+ liftIO $ hscTidy hsc_env simplified_guts let !partial_iface = {-# SCC "GHC.Driver.Main.mkPartialIface" #-}@@ -1432,7 +1441,7 @@ $ mkErrorMsgEnvelope l (pkgQual state) $ GhcDriverMessage $ DriverCannotImportUnsafeModule m - -- | Check the package a module resides in is trusted. Safe compiled+ -- Check the package a module resides in is trusted. Safe compiled -- modules are trusted without requiring that their package is trusted. For -- trustworthy modules, modules in the home package are trusted but -- otherwise we check the package trust flag.@@ -2028,7 +2037,7 @@ hscSimplify hsc_env plugins ds_result {- Tidy -}- (tidy_cg, mod_details) <- liftIO $ tidyProgram hsc_env simpl_mg+ (tidy_cg, mod_details) <- liftIO $ hscTidy hsc_env simpl_mg let !CgGuts{ cg_module = this_mod, cg_binds = core_binds,@@ -2197,6 +2206,44 @@ liftIO $ putDumpFileMaybe logger Opt_D_dump_parsed_ast "Parser AST" FormatHaskell (showAstData NoBlankSrcSpan NoBlankEpAnnotations thing) return thing++hscTidy :: HscEnv -> ModGuts -> IO (CgGuts, ModDetails)+hscTidy hsc_env guts = do+ let logger = hsc_logger hsc_env+ let this_mod = mg_module guts++ opts <- initTidyOpts hsc_env+ (cgguts, details) <- withTiming logger+ (text "CoreTidy"<+>brackets (ppr this_mod))+ (const ())+ $! {-# SCC "CoreTidy" #-} tidyProgram opts guts++ -- post tidy pretty-printing and linting...+ let tidy_rules = md_rules details+ let all_tidy_binds = cg_binds cgguts+ let print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) (mg_rdr_env guts)++ endPassIO hsc_env print_unqual CoreTidy all_tidy_binds tidy_rules++ -- If the endPass didn't print the rules, but ddump-rules is+ -- on, print now+ unless (logHasDumpFlag logger Opt_D_dump_simpl) $+ putDumpFileMaybe logger Opt_D_dump_rules+ (renderWithContext defaultSDocContext (ppr CoreTidy <+> text "rules"))+ FormatText+ (pprRulesForUser tidy_rules)++ -- Print one-line size info+ let cs = coreBindsStats all_tidy_binds+ putDumpFileMaybe logger Opt_D_dump_core_stats "Core Stats"+ FormatText+ (text "Tidy size (terms,types,coercions)"+ <+> ppr (moduleName this_mod) <> colon+ <+> int (cs_tm cs)+ <+> int (cs_ty cs)+ <+> int (cs_co cs))++ pure (cgguts, details) {- **********************************************************************
compiler/GHC/Driver/Make.hs view
@@ -15,7 +15,6 @@ {-# LANGUAGE TupleSections #-} {-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE CPP #-} {-# LANGUAGE RecordWildCards #-} -- -----------------------------------------------------------------------------@@ -62,7 +61,6 @@ import qualified GHC.Linker.Loader as Linker import GHC.Linker.Types -import GHC.Runtime.Context import GHC.Platform.Ways import GHC.Driver.Config.Finder (initFinderOpts)@@ -108,7 +106,6 @@ import GHC.Types.SourceError import GHC.Types.SrcLoc import GHC.Types.Unique.FM-import GHC.Types.Name import GHC.Types.PkgQual import GHC.Unit@@ -151,7 +148,7 @@ import Control.Monad.Trans.Maybe import GHC.Runtime.Loader import GHC.Rename.Names-+import GHC.Utils.Constants -- ----------------------------------------------------------------------------- -- Loading the program@@ -680,8 +677,6 @@ liftIO $ debugTraceMsg logger 2 (hang (text "Ready for upsweep") 2 (ppr build_plan)) - let direct_deps = mkDepsMap (mgModSummaries' mod_graph)- n_jobs <- case parMakeCount (hsc_dflags hsc_env) of Nothing -> liftIO getNumProcessors Just n -> return n@@ -689,7 +684,7 @@ setSession $ hscUpdateHUG (unitEnv_map pruneHomeUnitEnv) hsc_env hsc_env <- getSession (upsweep_ok, hsc_env1, new_cache) <- withDeferredDiagnostics $- liftIO $ upsweep n_jobs hsc_env mHscMessage (toCache pruned_cache) direct_deps build_plan+ liftIO $ upsweep n_jobs hsc_env mHscMessage (toCache pruned_cache) build_plan setSession hsc_env1 fmap (, new_cache) $ case upsweep_ok of Failed -> loadFinish upsweep_ok@@ -709,29 +704,6 @@ = do modifySession discardIC return all_ok --- | Discard the contents of the InteractiveContext, but keep the DynFlags and--- the loaded plugins. It will also keep ic_int_print and ic_monad if their--- names are from external packages.-discardIC :: HscEnv -> HscEnv-discardIC hsc_env- = hsc_env { hsc_IC = empty_ic { ic_int_print = new_ic_int_print- , ic_monad = new_ic_monad- , ic_plugins = old_plugins- } }- where- -- Force the new values for ic_int_print and ic_monad to avoid leaking old_ic- !new_ic_int_print = keep_external_name ic_int_print- !new_ic_monad = keep_external_name ic_monad- !old_plugins = ic_plugins old_ic- dflags = ic_dflags old_ic- old_ic = hsc_IC hsc_env- empty_ic = emptyInteractiveContext dflags- keep_external_name ic_name- | nameIsFromExternalPackage home_unit old_name = old_name- | otherwise = ic_name empty_ic- where- home_unit = hsc_home_unit hsc_env- old_name = ic_name old_ic -- | If there is no -o option, guess the name of target executable -- by using top-level source file name as a base.@@ -994,12 +966,11 @@ -- See Note [Upsweep] for a high-level description. interpretBuildPlan :: HomeUnitGraph -> M.Map ModNodeKeyWithUid HomeModInfo- -> (NodeKey -> [NodeKey]) -> [BuildPlan] -> IO ( Maybe [ModuleGraphNode] -- Is there an unresolved cycle , [MakeAction] -- Actions we need to run in order to build everything , IO [Maybe (Maybe HomeModInfo)]) -- An action to query to get all the built modules at the end.-interpretBuildPlan hug old_hpt deps_map plan = do+interpretBuildPlan hug old_hpt plan = do hug_var <- newMVar hug ((mcycle, plans), build_map) <- runStateT (buildLoop plan) (BuildLoopState M.empty 1 hug_var) return (mcycle, plans, collect_results (buildDep build_map))@@ -1041,7 +1012,7 @@ home_mod_map <- getBuildMap hug_var <- gets hug_var -- 1. Get the transitive dependencies of this module, by looking up in the dependency map- let direct_deps = deps_map (mkNodeKey mod)+ let direct_deps = nodeDependencies False mod doc_build_deps = map (expectJust "dep_map" . flip M.lookup home_mod_map) direct_deps build_deps = map snd doc_build_deps -- 2. Set the default way to build this node, not in a loop here@@ -1049,11 +1020,10 @@ case mod of InstantiationNode uid iu -> const Nothing <$> executeInstantiationNode mod_idx n_mods (wait_deps_hug hug_var build_deps) uid iu- ModuleNode build_deps ms -> do+ ModuleNode _build_deps ms -> do let !old_hmi = M.lookup (msKey ms) old_hpt rehydrate_mods = mapMaybe moduleGraphNodeModule <$> rehydrate_nodes- build_deps_vars = map snd $ map (expectJust "build_deps" . flip M.lookup home_mod_map) build_deps- hmi <- executeCompileNode mod_idx n_mods old_hmi (wait_deps_hug hug_var build_deps_vars) rehydrate_mods ms+ hmi <- executeCompileNode mod_idx n_mods old_hmi (wait_deps_hug hug_var build_deps) rehydrate_mods ms -- This global MVar is incrementally modified in order to avoid having to -- recreate the HPT before compiling each module which leads to a quadratic amount of work. hsc_env <- asks hsc_env@@ -1063,9 +1033,8 @@ maybeRehydrateAfter hmi new_hsc rehydrate_mods ) return (Just hmi')- LinkNode nks uid -> do- let link_deps = map snd $ map (\nk -> expectJust "build_deps_link" . flip M.lookup home_mod_map $ nk) nks- executeLinkNode (wait_deps_hug hug_var link_deps) (mod_idx, n_mods) uid nks+ LinkNode _nks uid -> do+ executeLinkNode (wait_deps_hug hug_var build_deps) (mod_idx, n_mods) uid direct_deps return Nothing @@ -1105,11 +1074,10 @@ -> HscEnv -- ^ The base HscEnv, which is augmented for each module -> Maybe Messager -> M.Map ModNodeKeyWithUid HomeModInfo- -> (NodeKey -> [NodeKey]) -- A function which computes the direct dependencies of a NodeKey -> [BuildPlan] -> IO (SuccessFlag, HscEnv, [HomeModInfo])-upsweep n_jobs hsc_env mHscMessage old_hpt direct_deps build_plan = do- (cycle, pipelines, collect_result) <- interpretBuildPlan (hsc_HUG hsc_env) old_hpt direct_deps build_plan+upsweep n_jobs hsc_env mHscMessage old_hpt build_plan = do+ (cycle, pipelines, collect_result) <- interpretBuildPlan (hsc_HUG hsc_env) old_hpt build_plan runPipelines n_jobs hsc_env mHscMessage pipelines res <- collect_result @@ -1364,14 +1332,6 @@ modNodeMapUnionWith :: (a -> a -> a) -> ModNodeMap a -> ModNodeMap a -> ModNodeMap a modNodeMapUnionWith f (ModNodeMap m) (ModNodeMap n) = ModNodeMap (M.unionWith f m n) --- | Efficiently construct a map from a NodeKey to its list of transitive dependencies-mkDepsMap :: [ModuleGraphNode] -> (NodeKey -> [NodeKey])-mkDepsMap nodes =- -- Important that we force this before returning a lambda so we can share the module graph- -- for each node- let !(mg, lookup_node) = moduleGraphNodes False nodes- in \nk -> map (mkNodeKey . node_payload) $ outgoingG mg (expectJust "mkDepsMap" (lookup_node nk))- -- | If there are {-# SOURCE #-} imports between strongly connected -- components in the topological sort, then those imports can -- definitely be replaced by ordinary non-SOURCE imports: if SOURCE@@ -1457,7 +1417,12 @@ in map Right instantiation_nodes ++ maybeToList (linkNodes (instantiation_nodes ++ summaries) uid hue) - calcDeps ms = [(ms_unitid ms, b, c) | (b, c) <- msDeps ms ]+ calcDeps ms =+ -- Add a dependency on the HsBoot file if it exists+ -- This gets passed to the loopImports function which just ignores it if it+ -- can't be found.+ [(ms_unitid ms, NoPkgQual, GWIB (noLoc $ ms_mod_name ms) IsBoot) | NotBoot <- [isBootSummary ms] ] +++ [(ms_unitid ms, b, c) | (b, c) <- msDeps ms ] logger = hsc_logger hsc_env roots = hsc_targets hsc_env@@ -1646,7 +1611,6 @@ -> IO [ModuleGraphNode] enableCodeGenForTH logger tmpfs unit_env = enableCodeGenWhen logger tmpfs TFL_CurrentModule TFL_GhcSession unit_env- where -- | Helper used to implement 'enableCodeGenForTH'. -- In particular, this enables@@ -1741,14 +1705,9 @@ -- #16331 - when no "internal interpreter" is available but we -- need to process some TemplateHaskell or QuasiQuotes, we automatically -- turn on -fexternal-interpreter.- ext_interp_enable ms = not host_internalInterpreter && internalInterpreter+ ext_interp_enable ms = not ghciSupported && internalInterpreter where lcl_dflags = ms_hspp_opts ms-#if defined(HAVE_INTERNAL_INTERPRETER)- host_internalInterpreter = True-#else- host_internalInterpreter = False-#endif internalInterpreter = not (gopt Opt_ExternalInterpreter lcl_dflags) @@ -1916,7 +1875,7 @@ -> IO SummariseResult -summariseModule hsc_env' home_unit old_summary_map is_boot (L loc wanted_mod) mb_pkg+summariseModule hsc_env' home_unit old_summary_map is_boot (L _ wanted_mod) mb_pkg maybe_buf excl_mods | wanted_mod `elem` excl_mods = return NotThere@@ -1933,12 +1892,9 @@ found <- findImportedModule hsc_env wanted_mod mb_pkg case found of Found location mod- | isJust (ml_hs_file location) -> do+ | isJust (ml_hs_file location) -> -- Home package- fresult <- just_found location mod- return $ case fresult of- Left err -> FoundHomeWithError (moduleUnitId mod, err)- Right ms -> FoundHome ms+ just_found location mod | VirtUnit iud <- moduleUnit mod , not (isHomeModule home_unit mod) -> return $ FoundInstantiation iud@@ -1960,8 +1916,14 @@ -- It might have been deleted since the Finder last found it maybe_h <- fileHashIfExists src_fn case maybe_h of- Nothing -> return $ Left $ noHsFileErr loc src_fn- Just h -> new_summary_cache_check location' mod src_fn h+ -- This situation can also happen if we have found the .hs file but the+ -- .hs-boot file doesn't exist.+ Nothing -> return NotThere+ Just h -> do+ fresult <- new_summary_cache_check location' mod src_fn h+ return $ case fresult of+ Left err -> FoundHomeWithError (moduleUnitId mod, err)+ Right ms -> FoundHome ms new_summary_cache_check loc mod src_fn h | Just old_summary <- Map.lookup src_fn old_summary_map =@@ -2149,9 +2111,11 @@ = mkPlainErrorMsgEnvelope loc $ GhcDriverMessage $ DriverUnknownMessage $ mkPlainError noHints $ cannotFindModule hsc_env wanted_mod err +{- noHsFileErr :: SrcSpan -> String -> DriverMessages noHsFileErr loc path = singleMessage $ mkPlainErrorMsgEnvelope loc (DriverFileNotFound path)+ -} moduleNotFoundErr :: ModuleName -> DriverMessages moduleNotFoundErr mod = singleMessage $ mkPlainErrorMsgEnvelope noSrcSpan (DriverModuleNotFound mod)@@ -2448,7 +2412,7 @@ Solution: **rehydration**. *Before compiling `R.hs`*, rehydrate all the ModIfaces below it that depend on R.hs-boot. To rehydrate a ModIface, call-`rehydrateIface` to convert it to a ModDetails. It's just a de-serialisation+`typecheckIface` to convert it to a ModDetails. It's just a de-serialisation step, no type inference, just lookups. Now `S` will be bound to a thunk that, when forced, will "see" the final binding
compiler/GHC/Hs/Syn/Type.hs view
@@ -129,9 +129,8 @@ Nothing -> asi_ty where asi_ty = arithSeqInfoType asi-hsExprType (HsBracket v _) = dataConCantHappen v-hsExprType (HsRnBracketOut v _ _) = dataConCantHappen v-hsExprType (HsTcBracketOut ty _wrap _bracket _pending) = ty+hsExprType (HsTypedBracket (HsBracketTc _ ty _wrap _pending) _) = ty+hsExprType (HsUntypedBracket (HsBracketTc _ ty _wrap _pending) _) = ty hsExprType e@(HsSpliceE{}) = pprPanic "hsExprType: Unexpected HsSpliceE" (ppr e) -- Typed splices should have been eliminated during zonking, but we
compiler/GHC/HsToCore.hs view
@@ -225,7 +225,7 @@ ; foreign_files <- readIORef th_foreign_files_var - ; (doc_hdr, decl_docs, arg_docs) <- extractDocs tcg_env+ ; docs <- extractDocs dflags tcg_env ; let mod_guts = ModGuts { mg_module = mod,@@ -255,9 +255,7 @@ mg_safe_haskell = safe_mode, mg_trust_pkg = imp_trust_own_pkg imports, mg_complete_matches = complete_matches,- mg_doc_hdr = doc_hdr,- mg_decl_docs = decl_docs,- mg_arg_docs = arg_docs+ mg_docs = docs } ; return (msgs, Just mod_guts) }}}}
compiler/GHC/HsToCore/Binds.hs view
@@ -201,10 +201,12 @@ else [] ; return (force_var', sel_binds) } -dsHsBind dflags (AbsBinds { abs_tvs = tyvars, abs_ev_vars = dicts- , abs_exports = exports- , abs_ev_binds = ev_binds- , abs_binds = binds, abs_sig = has_sig })+dsHsBind+ dflags+ (XHsBindsLR (AbsBinds { abs_tvs = tyvars, abs_ev_vars = dicts+ , abs_exports = exports+ , abs_ev_binds = ev_binds+ , abs_binds = binds, abs_sig = has_sig })) = do { ds_binds <- addTyCs FromSource (listToBag dicts) $ dsLHsBinds binds -- addTyCs: push type constraints deeper@@ -220,7 +222,7 @@ ----------------------- dsAbsBinds :: DynFlags- -> [TyVar] -> [EvVar] -> [ABExport GhcTc]+ -> [TyVar] -> [EvVar] -> [ABExport] -> [CoreBind] -- Desugared evidence bindings -> ([Id], [(Id,CoreExpr)]) -- Desugared value bindings -> Bool -- Single binding with signature@@ -271,7 +273,7 @@ -- lcl_id{inl-prag} = rhs -- Auxiliary binds -- gbl_id = lcl_id |> co -- Main binds | null tyvars, null dicts- = do { let mk_main :: ABExport GhcTc -> DsM (Id, CoreExpr)+ = do { let mk_main :: ABExport -> DsM (Id, CoreExpr) mk_main (ABE { abe_poly = gbl_id, abe_mono = lcl_id , abe_wrap = wrap }) -- No SpecPrags (no dicts)@@ -360,7 +362,7 @@ [] lcls -- find exports or make up new exports for force variables- get_exports :: [Id] -> DsM ([Id], [ABExport GhcTc])+ get_exports :: [Id] -> DsM ([Id], [ABExport]) get_exports lcls = foldM (\(glbls, exports) lcl -> case lookupVarEnv global_env lcl of@@ -373,8 +375,7 @@ mk_export local = do global <- newSysLocalDs Many (exprType (mkLams tyvars (mkLams dicts (Var local))))- return (ABE { abe_ext = noExtField- , abe_poly = global+ return (ABE { abe_poly = global , abe_mono = local , abe_wrap = WpHole , abe_prags = SpecPrags [] })@@ -398,6 +399,7 @@ = case inlinePragmaSpec inline_prag of NoUserInlinePrag -> (gbl_id, rhs) NoInline {} -> (gbl_id, rhs)+ Opaque {} -> (gbl_id, rhs) Inlinable {} -> (gbl_id `setIdUnfolding` inlinable_unf, rhs) Inline {} -> inline_pair where@@ -768,6 +770,7 @@ -- phase specification in the SPECIALISE pragma no_act_spec = case inlinePragmaSpec spec_inl of NoInline _ -> isNeverActive spec_prag_act+ Opaque _ -> isNeverActive spec_prag_act _ -> isAlwaysActive spec_prag_act rule_act | no_act_spec = inlinePragmaActivation id_inl -- Inherit | otherwise = spec_prag_act -- Specified by user
compiler/GHC/HsToCore/Coverage.hs view
@@ -285,12 +285,13 @@ addTickLHsBinds = mapBagM addTickLHsBind addTickLHsBind :: LHsBind GhcTc -> TM (LHsBind GhcTc)-addTickLHsBind (L pos bind@(AbsBinds { abs_binds = binds,- abs_exports = abs_exports })) =+addTickLHsBind (L pos (XHsBindsLR bind@(AbsBinds { abs_binds = binds+ , abs_exports = abs_exports+ }))) = withEnv add_exports $ withEnv add_inlines $ do binds' <- addTickLHsBinds binds- return $ L pos $ bind { abs_binds = binds' }+ return $ L pos $ XHsBindsLR $ bind { abs_binds = binds' } where -- in AbsBinds, the Id on each binding is not the actual top-level -- Id that we are defining, they are related by the abs_exports@@ -637,9 +638,8 @@ addTickHsExpr (HsPragE x p e) = liftM (HsPragE x p) (addTickLHsExpr e)-addTickHsExpr e@(HsBracket {}) = return e-addTickHsExpr e@(HsTcBracketOut {}) = return e-addTickHsExpr e@(HsRnBracketOut {}) = return e+addTickHsExpr e@(HsTypedBracket {}) = return e+addTickHsExpr e@(HsUntypedBracket{}) = return e addTickHsExpr e@(HsSpliceE {}) = return e addTickHsExpr e@(HsGetField {}) = return e addTickHsExpr e@(HsProjection {}) = return e@@ -1229,7 +1229,7 @@ -> TM CoreTickish mkTickish boxLabel countEntries topOnly pos fvs decl_path = do - let ids = filter (not . isUnliftedType . idType) $ nonDetOccEnvElts fvs+ let ids = filter (not . mightBeUnliftedType . idType) $ nonDetOccEnvElts fvs -- unlifted types cause two problems here: -- * we can't bind them at the GHCi prompt -- (bindLocalsAtBreakpoint already filters them out),@@ -1343,23 +1343,18 @@ hpcInitCode :: Platform -> Module -> HpcInfo -> CStub hpcInitCode _ _ (NoHpcInfo {}) = mempty hpcInitCode platform this_mod (HpcInfo tickCount hashNo)- = CStub $ vcat- [ text "static void hpc_init_" <> ppr this_mod- <> text "(void) __attribute__((constructor));"- , text "static void hpc_init_" <> ppr this_mod <> text "(void)"- , braces (vcat [- text "extern StgWord64 " <> tickboxes <>- text "[]" <> semi,- text "hs_hpc_module" <>- parens (hcat (punctuate comma [- doubleQuotes full_name_str,- int tickCount, -- really StgWord32- int hashNo, -- really StgWord32- tickboxes- ])) <> semi- ])- ]+ = initializerCStub platform fn_name decls body where+ fn_name = mkInitializerStubLabel this_mod "hpc"+ decls = text "extern StgWord64 " <> tickboxes <> text "[]" <> semi+ body = text "hs_hpc_module" <>+ parens (hcat (punctuate comma [+ doubleQuotes full_name_str,+ int tickCount, -- really StgWord32+ int hashNo, -- really StgWord32+ tickboxes+ ])) <> semi+ tickboxes = pprCLabel platform CStyle (mkHpcTicksLabel $ this_mod) module_name = hcat (map (text.charToC) $ BS.unpack $
compiler/GHC/HsToCore/Docs.hs view
@@ -8,8 +8,6 @@ {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE BangPatterns #-} -{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}- module GHC.HsToCore.Docs where import GHC.Prelude@@ -32,89 +30,237 @@ import Data.Bifunctor (first) import Data.IntMap (IntMap) import qualified Data.IntMap as IM-import Data.Map (Map)+import Data.Map.Strict (Map) import qualified Data.Map as M+import qualified Data.Set as Set import Data.Maybe import Data.Semigroup import GHC.IORef (readIORef)+import GHC.Unit.Types+import GHC.Hs+import GHC.Types.Avail+import GHC.Unit.Module+import qualified Data.List.NonEmpty as NonEmpty+import Data.List.NonEmpty (NonEmpty ((:|)))+import GHC.Unit.Module.Imported+import GHC.Driver.Session+import GHC.Types.TypeEnv+import GHC.Types.Id+import GHC.Types.Unique.Map -- | Extract docs from renamer output. -- This is monadic since we need to be able to read documentation added from -- Template Haskell's @putDoc@, which is stored in 'tcg_th_docs'. extractDocs :: MonadIO m- => TcGblEnv- -> m (Maybe HsDocString, DeclDocMap, ArgDocMap)+ => DynFlags -> TcGblEnv+ -> m (Maybe Docs) -- ^ -- 1. Module header -- 2. Docs on top level declarations -- 3. Docs on arguments-extractDocs TcGblEnv { tcg_semantic_mod = mod- , tcg_rn_decls = mb_rn_decls- , tcg_insts = insts- , tcg_fam_insts = fam_insts- , tcg_doc_hdr = mb_doc_hdr- , tcg_th_docs = th_docs_var- } = do+extractDocs dflags+ TcGblEnv { tcg_semantic_mod = semantic_mdl+ , tcg_mod = mdl+ , tcg_rn_decls = Just rn_decls+ , tcg_rn_exports = mb_rn_exports+ , tcg_exports = all_exports+ , tcg_imports = import_avails+ , tcg_insts = insts+ , tcg_fam_insts = fam_insts+ , tcg_doc_hdr = mb_doc_hdr+ , tcg_th_docs = th_docs_var+ , tcg_type_env = ty_env+ } = do th_docs <- liftIO $ readIORef th_docs_var- let doc_hdr = th_doc_hdr <|> (unLoc <$> mb_doc_hdr)- ExtractedTHDocs- th_doc_hdr- (DeclDocMap th_doc_map)- (ArgDocMap th_arg_map)- (DeclDocMap th_inst_map) = extractTHDocs th_docs- return- ( doc_hdr- , DeclDocMap (th_doc_map <> th_inst_map <> doc_map)- , ArgDocMap (th_arg_map `unionArgMaps` arg_map)- )+ let doc_hdr = (unLoc <$> mb_doc_hdr)+ ExtractedTHDocs th_hdr th_decl_docs th_arg_docs th_inst_docs = extractTHDocs th_docs+ mod_docs+ = Docs+ { docs_mod_hdr = th_hdr <|> doc_hdr+ -- Left biased union (see #21220)+ , docs_decls = plusUniqMap_C (\a _ -> a)+ ((:[]) <$> th_decl_docs `plusUniqMap` th_inst_docs)+ -- These will not clash so safe to use plusUniqMap+ doc_map+ , docs_args = th_arg_docs `unionArgMaps` arg_map+ , docs_structure = doc_structure+ , docs_named_chunks = named_chunks+ , docs_haddock_opts = haddockOptions dflags+ , docs_language = language_+ , docs_extensions = exts+ }+ pure (Just mod_docs) where- (doc_map, arg_map) = maybe (M.empty, M.empty)- (mkMaps local_insts)- mb_decls_with_docs- mb_decls_with_docs = topDecls <$> mb_rn_decls- local_insts = filter (nameIsLocalOrFrom mod)+ exts = extensionFlags dflags+ language_ = language dflags++ -- We need to lookup the Names for default methods, so we+ -- can put them in the correct map+ -- See Note [default method Name] in GHC.Iface.Recomp+ def_meths_env = mkOccEnv [(occ, nm)+ | id <- typeEnvIds ty_env+ , let nm = idName id+ occ = nameOccName nm+ , isDefaultMethodOcc occ+ ]++ (doc_map, arg_map) = mkMaps def_meths_env local_insts decls_with_docs+ decls_with_docs = topDecls rn_decls+ local_insts = filter (nameIsLocalOrFrom semantic_mdl) $ map getName insts ++ map getName fam_insts+ doc_structure = mkDocStructure mdl import_avails mb_rn_exports rn_decls+ all_exports def_meths_env+ named_chunks = getNamedChunks (isJust mb_rn_exports) rn_decls+extractDocs _ _ = pure Nothing +-- | If we have an explicit export list, we extract the documentation structure+-- from that.+-- Otherwise we use the renamed exports and declarations.+mkDocStructure :: Module -- ^ The current module+ -> ImportAvails -- ^ Imports+ -> Maybe [(LIE GhcRn, Avails)] -- ^ Explicit export list+ -> HsGroup GhcRn+ -> [AvailInfo] -- ^ All exports+ -> OccEnv Name -- ^ Default Methods+ -> DocStructure+mkDocStructure mdl import_avails (Just export_list) _ _ _ =+ mkDocStructureFromExportList mdl import_avails export_list+mkDocStructure _ _ Nothing rn_decls all_exports def_meths_env =+ mkDocStructureFromDecls def_meths_env all_exports rn_decls++-- TODO:+-- * Maybe remove items that export nothing?+-- * Combine sequences of DsiExports?+-- * Check the ordering of avails in DsiModExport+mkDocStructureFromExportList+ :: Module -- ^ The current module+ -> ImportAvails+ -> [(LIE GhcRn, Avails)] -- ^ Explicit export list+ -> DocStructure+mkDocStructureFromExportList mdl import_avails export_list =+ toDocStructure . first unLoc <$> export_list+ where+ toDocStructure :: (IE GhcRn, Avails) -> DocStructureItem+ toDocStructure = \case+ (IEModuleContents _ lmn, avails) -> moduleExport (unLoc lmn) avails+ (IEGroup _ level doc, _) -> DsiSectionHeading level (unLoc doc)+ (IEDoc _ doc, _) -> DsiDocChunk (unLoc doc)+ (IEDocNamed _ name, _) -> DsiNamedChunkRef name+ (_, avails) -> DsiExports (nubAvails avails)++ moduleExport :: ModuleName -- Alias+ -> Avails+ -> DocStructureItem+ moduleExport alias avails =+ DsiModExport (nubSortNE orig_names) (nubAvails avails)+ where+ orig_names = M.findWithDefault aliasErr alias aliasMap+ aliasErr = error $ "mkDocStructureFromExportList: "+ ++ (moduleNameString . moduleName) mdl+ ++ ": Can't find alias " ++ moduleNameString alias+ nubSortNE = NonEmpty.fromList .+ Set.toList .+ Set.fromList .+ NonEmpty.toList++ -- Map from aliases to true module names.+ aliasMap :: Map ModuleName (NonEmpty ModuleName)+ aliasMap =+ M.fromListWith (<>) $+ (this_mdl_name, this_mdl_name :| [])+ : (flip concatMap (moduleEnvToList imported) $ \(mdl, imvs) ->+ [(imv_name imv, moduleName mdl :| []) | imv <- imvs])+ where+ this_mdl_name = moduleName mdl++ imported :: ModuleEnv [ImportedModsVal]+ imported = mapModuleEnv importedByUser (imp_mods import_avails)++-- | Figure out the documentation structure by correlating+-- the module exports with the located declarations.+mkDocStructureFromDecls :: OccEnv Name -- ^ The default method environment+ -> [AvailInfo] -- ^ All exports, unordered+ -> HsGroup GhcRn+ -> DocStructure+mkDocStructureFromDecls env all_exports decls =+ map unLoc (sortLocated (docs ++ avails))+ where+ avails :: [Located DocStructureItem]+ avails = flip fmap all_exports $ \avail ->+ case M.lookup (availName avail) name_locs of+ Just loc -> L loc (DsiExports [avail])+ -- FIXME: This is just a workaround that we use when handling e.g.+ -- associated data families like in the html-test Instances.hs.+ Nothing -> noLoc (DsiExports [avail])+ -- Nothing -> panicDoc "mkDocStructureFromDecls: No loc found for"+ -- (ppr avail)++ docs = mapMaybe structuralDoc (hs_docs decls)++ structuralDoc :: LDocDecl GhcRn+ -> Maybe (Located DocStructureItem)+ structuralDoc = \case+ L loc (DocCommentNamed _name doc) ->+ -- TODO: Is this correct?+ -- NB: There is no export list where we could reference the named chunk.+ Just (L (locA loc) (DsiDocChunk (unLoc doc)))++ L loc (DocGroup level doc) ->+ Just (L (locA loc) (DsiSectionHeading level (unLoc doc)))++ _ -> Nothing++ name_locs = M.fromList (concatMap ldeclNames (ungroup decls))+ ldeclNames (L loc d) = zip (getMainDeclBinder env d) (repeat (locA loc))++-- | Extract named documentation chunks from the renamed declarations.+--+-- If there is no explicit export list, we simply return an empty map+-- since there would be no way to link to a named chunk.+getNamedChunks :: Bool -- ^ Do we have an explicit export list?+ -> HsGroup (GhcPass pass)+ -> Map String (HsDoc (GhcPass pass))+getNamedChunks True decls =+ M.fromList $ flip mapMaybe (unLoc <$> hs_docs decls) $ \case+ DocCommentNamed name doc -> Just (name, unLoc doc)+ _ -> Nothing+getNamedChunks False _ = M.empty+ -- | Create decl and arg doc-maps by looping through the declarations. -- For each declaration, find its names, its subordinates, and its doc strings.-mkMaps :: [Name]- -> [(LHsDecl GhcRn, [HsDocString])]- -> (Map Name (HsDocString), Map Name (IntMap HsDocString))-mkMaps instances decls =- ( f' (map (nubByName fst) decls')- , f (filterMapping (not . IM.null) args)+mkMaps :: OccEnv Name+ -> [Name]+ -> [(LHsDecl GhcRn, [HsDoc GhcRn])]+ -> (UniqMap Name [HsDoc GhcRn], UniqMap Name (IntMap (HsDoc GhcRn)))+mkMaps env instances decls =+ ( listsToMapWith (++) (map (nubByName fst) decls')+ , listsToMapWith (<>) (filterMapping (not . IM.null) args) ) where (decls', args) = unzip (map mappings decls) - f :: (Ord a, Semigroup b) => [[(a, b)]] -> Map a b- f = M.fromListWith (<>) . concat-- f' :: Ord a => [[(a, HsDocString)]] -> Map a HsDocString- f' = M.fromListWith appendDocs . concat+ listsToMapWith f = listToUniqMap_C f . concat filterMapping :: (b -> Bool) -> [[(a, b)]] -> [[(a, b)]] filterMapping p = map (filter (p . snd)) - mappings :: (LHsDecl GhcRn, [HsDocString])- -> ( [(Name, HsDocString)]- , [(Name, IntMap HsDocString)]+ mappings :: (LHsDecl GhcRn, [HsDoc GhcRn])+ -> ( [(Name, [HsDoc GhcRn])]+ , [(Name, IntMap (HsDoc GhcRn))] )- mappings (L (SrcSpanAnn _ (RealSrcSpan l _)) decl, docStrs) =+ mappings (L (SrcSpanAnn _ (RealSrcSpan l _)) decl, doc) = (dm, am) where- doc = concatDocs docStrs args = declTypeDocs decl - subs :: [(Name, [HsDocString], IntMap HsDocString)]- subs = subordinates instanceMap decl+ subs :: [(Name, [HsDoc GhcRn], IntMap (HsDoc GhcRn))]+ subs = subordinates env instanceMap decl - (subDocs, subArgs) =- unzip (map (\(_, strs, m) -> (concatDocs strs, m)) subs)+ (subNs, subDocs, subArgs) =+ unzip3 subs ns = names l decl- subNs = [ n | (n, _, _) <- subs ]- dm = [(n, d) | (n, Just d) <- zip ns (repeat doc) ++ zip subNs subDocs]+ dm = [(n, d) | (n, d) <- zip ns (repeat doc) ++ zip subNs subDocs, not $ all (isEmptyDocString . hsDocString) d] am = [(n, args) | n <- ns] ++ zip subNs subArgs mappings (L (SrcSpanAnn _ (UnhelpfulSpan _)) _, _) = ([], []) @@ -124,7 +270,7 @@ names :: RealSrcSpan -> HsDecl GhcRn -> [Name] names _ (InstD _ d) = maybeToList $ lookupSrcSpan (getInstLoc d) instanceMap names l (DerivD {}) = maybeToList (M.lookup l instanceMap) -- See Note [1].- names _ decl = getMainDeclBinder decl+ names _ decl = getMainDeclBinder env decl {- Note [1]:@@ -135,27 +281,37 @@ user-written. This lets us relate Names (from ClsInsts) to comments (associated with InstDecls and DerivDecls). -}-getMainDeclBinder :: (Anno (IdGhcP p) ~ SrcSpanAnnN, CollectPass (GhcPass p))- => HsDecl (GhcPass p) -> [IdP (GhcPass p)]-getMainDeclBinder (TyClD _ d) = [tcdName d]-getMainDeclBinder (ValD _ d) =++getMainDeclBinder+ :: OccEnv Name -- ^ Default method environment for this module. See Note [default method Name] in GHC.Iface.Recomp+ -> HsDecl GhcRn -> [Name]+getMainDeclBinder _ (TyClD _ d) = [tcdName d]+getMainDeclBinder _ (ValD _ d) = case collectHsBindBinders CollNoDictBinders d of [] -> [] (name:_) -> [name]-getMainDeclBinder (SigD _ d) = sigNameNoLoc d-getMainDeclBinder (ForD _ (ForeignImport _ name _ _)) = [unLoc name]-getMainDeclBinder (ForD _ (ForeignExport _ _ _ _)) = []-getMainDeclBinder _ = []+getMainDeclBinder env (SigD _ d) = sigNameNoLoc env d+getMainDeclBinder _ (ForD _ (ForeignImport _ name _ _)) = [unLoc name]+getMainDeclBinder _ (ForD _ (ForeignExport _ _ _ _)) = []+getMainDeclBinder _ _ = [] -sigNameNoLoc :: forall pass. UnXRec pass => Sig pass -> [IdP pass]-sigNameNoLoc (TypeSig _ ns _) = map (unXRec @pass) ns-sigNameNoLoc (ClassOpSig _ _ ns _) = map (unXRec @pass) ns-sigNameNoLoc (PatSynSig _ ns _) = map (unXRec @pass) ns-sigNameNoLoc (SpecSig _ n _ _) = [unXRec @pass n]-sigNameNoLoc (InlineSig _ n _) = [unXRec @pass n]-sigNameNoLoc (FixSig _ (FixitySig _ ns _)) = map (unXRec @pass) ns-sigNameNoLoc _ = []+-- | The "OccEnv Name" is the default method environment for this module+-- Ultimately, the a special "defaultMethodOcc" name is used for+-- the signatures on bindings for default methods. Unfortunately, this+-- name isn't generated until typechecking, so it is not in the renamed AST.+-- We have to look it up from the 'OccEnv' parameter constructed from the typechecked+-- AST.+-- See also Note [default method Name] in GHC.Iface.Recomp+sigNameNoLoc :: forall a . (UnXRec a, HasOccName (IdP a)) => OccEnv (IdP a) -> Sig a -> [IdP a]+sigNameNoLoc _ (TypeSig _ ns _) = map (unXRec @a) ns+sigNameNoLoc _ (ClassOpSig _ False ns _) = map (unXRec @a) ns+sigNameNoLoc env (ClassOpSig _ True ns _) = mapMaybe (lookupOccEnv env . mkDefaultMethodOcc . occName) $ map (unXRec @a) ns+sigNameNoLoc _ (PatSynSig _ ns _) = map (unXRec @a) ns+sigNameNoLoc _ (SpecSig _ n _ _) = [unXRec @a n]+sigNameNoLoc _ (InlineSig _ n _) = [unXRec @a n]+sigNameNoLoc _ (FixSig _ (FixitySig _ ns _)) = map (unXRec @a) ns+sigNameNoLoc _ _ = [] -- Extract the source location where an instance is defined. This is used -- to correlate InstDecls with their Instance/CoAxiom Names, via the@@ -180,15 +336,21 @@ -- | Get all subordinate declarations inside a declaration, and their docs. -- A subordinate declaration is something like the associate type or data -- family of a type class.-subordinates :: Map RealSrcSpan Name+subordinates :: OccEnv Name -- ^ The default method environment+ -> Map RealSrcSpan Name -> HsDecl GhcRn- -> [(Name, [HsDocString], IntMap HsDocString)]-subordinates instMap decl = case decl of- InstD _ (ClsInstD _ d) -> do- DataFamInstDecl { dfid_eqn =- FamEqn { feqn_tycon = L l _- , feqn_rhs = defn }} <- unLoc <$> cid_datafam_insts d- [ (n, [], IM.empty) | Just n <- [lookupSrcSpan (locA l) instMap] ] ++ dataSubs defn+ -> [(Name, [HsDoc GhcRn], IntMap (HsDoc GhcRn))]+subordinates env instMap decl = case decl of+ InstD _ (ClsInstD _ d) -> let+ data_fams = do+ DataFamInstDecl { dfid_eqn =+ FamEqn { feqn_tycon = L l _+ , feqn_rhs = defn }} <- unLoc <$> cid_datafam_insts d+ [ (n, [], IM.empty) | Just n <- [lookupSrcSpan (locA l) instMap] ] ++ dataSubs defn+ ty_fams = do+ TyFamInstDecl { tfid_eqn = FamEqn { feqn_tycon = L l _ } } <- unLoc <$> cid_tyfam_insts d+ [ (n, [], IM.empty) | Just n <- [lookupSrcSpan (locA l) instMap] ]+ in data_fams ++ ty_fams InstD _ (DataFamInstD _ (DataFamInstDecl d)) -> dataSubs (feqn_rhs d)@@ -198,11 +360,11 @@ where classSubs dd = [ (name, doc, declTypeDocs d) | (L _ d, doc) <- classDecls dd- , name <- getMainDeclBinder d, not (isValD d)+ , name <- getMainDeclBinder env d, not (isValD d) ] dataSubs :: HsDataDefn GhcRn- -> [(Name, [HsDocString], IntMap HsDocString)]- dataSubs dd = constrs ++ fields ++ derivs+ -> [(Name, [HsDoc GhcRn], IntMap (HsDoc GhcRn))]+ dataSubs dd = constrs ++ fields ++ derivs where cons = map unLoc $ (dd_cons dd) constrs = [ ( unLoc cname@@ -220,13 +382,13 @@ dd_derivs dd , Just instName <- [lookupSrcSpan l instMap] ] - extract_deriv_clause_tys :: LDerivClauseTys GhcRn -> [(SrcSpan, LHsDocString)]+ extract_deriv_clause_tys :: LDerivClauseTys GhcRn -> [(SrcSpan, LHsDoc GhcRn)] extract_deriv_clause_tys (L _ dct) = case dct of DctSingle _ ty -> maybeToList $ extract_deriv_ty ty DctMulti _ tys -> mapMaybe extract_deriv_ty tys - extract_deriv_ty :: LHsSigType GhcRn -> Maybe (SrcSpan, LHsDocString)+ extract_deriv_ty :: LHsSigType GhcRn -> Maybe (SrcSpan, LHsDoc GhcRn) extract_deriv_ty (L l (HsSig{sig_body = L _ ty})) = case ty of -- deriving (C a {- ^ Doc comment -})@@ -234,25 +396,25 @@ _ -> Nothing -- | Extract constructor argument docs from inside constructor decls.-conArgDocs :: ConDecl GhcRn -> IntMap HsDocString+conArgDocs :: ConDecl GhcRn -> IntMap (HsDoc GhcRn) conArgDocs (ConDeclH98{con_args = args}) = h98ConArgDocs args conArgDocs (ConDeclGADT{con_g_args = args, con_res_ty = res_ty}) = gadtConArgDocs args (unLoc res_ty) -h98ConArgDocs :: HsConDeclH98Details GhcRn -> IntMap HsDocString+h98ConArgDocs :: HsConDeclH98Details GhcRn -> IntMap (HsDoc GhcRn) h98ConArgDocs con_args = case con_args of PrefixCon _ args -> con_arg_docs 0 $ map (unLoc . hsScaledThing) args InfixCon arg1 arg2 -> con_arg_docs 0 [ unLoc (hsScaledThing arg1) , unLoc (hsScaledThing arg2) ] RecCon _ -> IM.empty -gadtConArgDocs :: HsConDeclGADTDetails GhcRn -> HsType GhcRn -> IntMap HsDocString+gadtConArgDocs :: HsConDeclGADTDetails GhcRn -> HsType GhcRn -> IntMap (HsDoc GhcRn) gadtConArgDocs con_args res_ty = case con_args of PrefixConGADT args -> con_arg_docs 0 $ map (unLoc . hsScaledThing) args ++ [res_ty] RecConGADT _ _ -> con_arg_docs 1 [res_ty] -con_arg_docs :: Int -> [HsType GhcRn] -> IntMap HsDocString+con_arg_docs :: Int -> [HsType GhcRn] -> IntMap (HsDoc GhcRn) con_arg_docs n = IM.fromList . catMaybes . zipWith f [n..] where f n (HsDocTy _ _ lds) = Just (n, unLoc lds)@@ -265,7 +427,7 @@ -- | All the sub declarations of a class (that we handle), ordered by -- source location, with documentation attached if it exists.-classDecls :: TyClDecl GhcRn -> [(LHsDecl GhcRn, [HsDocString])]+classDecls :: TyClDecl GhcRn -> [(LHsDecl GhcRn, [HsDoc GhcRn])] classDecls class_ = filterDecls . collectDocs . sortLocatedA $ decls where decls = docs ++ defs ++ sigs ++ ats@@ -275,7 +437,7 @@ ats = mkDecls tcdATs (TyClD noExtField . FamDecl noExtField) class_ -- | Extract function argument docs from inside top-level decls.-declTypeDocs :: HsDecl GhcRn -> IntMap (HsDocString)+declTypeDocs :: HsDecl GhcRn -> IntMap (HsDoc GhcRn) declTypeDocs = \case SigD _ (TypeSig _ _ ty) -> sigTypeDocs (unLoc (dropWildCards ty)) SigD _ (ClassOpSig _ _ _ ty) -> sigTypeDocs (unLoc ty)@@ -296,7 +458,7 @@ y = f x -- | Extract function argument docs from inside types.-typeDocs :: HsType GhcRn -> IntMap HsDocString+typeDocs :: HsType GhcRn -> IntMap (HsDoc GhcRn) typeDocs = go 0 where go n = \case@@ -308,12 +470,12 @@ _ -> IM.empty -- | Extract function argument docs from inside types.-sigTypeDocs :: HsSigType GhcRn -> IntMap HsDocString+sigTypeDocs :: HsSigType GhcRn -> IntMap (HsDoc GhcRn) sigTypeDocs (HsSig{sig_body = body}) = typeDocs (unLoc body) -- | The top-level declarations of a module that we care about, -- ordered by source location, with documentation attached if it exists.-topDecls :: HsGroup GhcRn -> [(LHsDecl GhcRn, [HsDocString])]+topDecls :: HsGroup GhcRn -> [(LHsDecl GhcRn, [HsDoc GhcRn])] topDecls = filterClasses . filterDecls . collectDocs . sortLocatedA . ungroup -- | Take all declarations except pragmas, infix decls, rules from an 'HsGroup'.@@ -340,14 +502,14 @@ -- | Collect docs and attach them to the right declarations. -- -- A declaration may have multiple doc strings attached to it.-collectDocs :: forall p. UnXRec p => [LHsDecl p] -> [(LHsDecl p, [HsDocString])]+collectDocs :: forall p. UnXRec p => [LHsDecl p] -> [(LHsDecl p, [HsDoc p])] -- ^ This is an example. collectDocs = go [] Nothing where go docs mprev decls = case (decls, mprev) of- ((unXRec @p -> DocD _ (DocCommentNext s)) : ds, Nothing) -> go (s:docs) Nothing ds- ((unXRec @p -> DocD _ (DocCommentNext s)) : ds, Just prev) -> finished prev docs $ go [s] Nothing ds- ((unXRec @p -> DocD _ (DocCommentPrev s)) : ds, mprev) -> go (s:docs) mprev ds+ ((unXRec @p -> DocD _ (DocCommentNext s)) : ds, Nothing) -> go (unLoc s:docs) Nothing ds+ ((unXRec @p -> DocD _ (DocCommentNext s)) : ds, Just prev) -> finished prev docs $ go [unLoc s] Nothing ds+ ((unXRec @p -> DocD _ (DocCommentPrev s)) : ds, mprev) -> go (unLoc s:docs) mprev ds (d : ds, Nothing) -> go docs (Just d) ds (d : ds, Just prev) -> finished prev docs $ go [] (Just d) ds ([] , Nothing) -> []@@ -401,14 +563,15 @@ extractTHDocs docs = -- Split up docs into separate maps for each 'DocLoc' type ExtractedTHDocs- docHeader- (DeclDocMap (searchDocs decl))- (ArgDocMap (searchDocs args))- (DeclDocMap (searchDocs insts))+ { ethd_mod_header = docHeader+ , ethd_decl_docs = searchDocs decl+ , ethd_arg_docs = searchDocs args+ , ethd_inst_docs = searchDocs insts+ } where- docHeader :: Maybe HsDocString+ docHeader :: Maybe (HsDoc GhcRn) docHeader- | ((_, s):_) <- filter isModDoc (M.toList docs) = Just (mkHsDocString s)+ | ((_, s):_) <- filter isModDoc (M.toList docs) = Just s | otherwise = Nothing isModDoc (ModuleDoc, _) = True@@ -417,38 +580,40 @@ -- Folds over the docs, applying 'f' as the accumulating function. -- We use different accumulating functions to sift out the specific types of -- documentation- searchDocs :: Monoid a => (a -> (DocLoc, String) -> a) -> a- searchDocs f = foldl' f mempty $ M.toList docs+ searchDocs :: (UniqMap Name a -> (DocLoc, HsDoc GhcRn) -> UniqMap Name a) -> UniqMap Name a+ searchDocs f = foldl' f emptyUniqMap $ M.toList docs -- Pick out the declaration docs- decl acc ((DeclDoc name), s) = M.insert name (mkHsDocString s) acc+ decl acc ((DeclDoc name), s) = addToUniqMap acc name s decl acc _ = acc -- Pick out the instance docs- insts acc ((InstDoc name), s) = M.insert name (mkHsDocString s) acc+ insts acc ((InstDoc name), s) = addToUniqMap acc name s insts acc _ = acc -- Pick out the argument docs- args :: Map Name (IntMap HsDocString)- -> (DocLoc, String)- -> Map Name (IntMap HsDocString)+ args :: UniqMap Name (IntMap (HsDoc GhcRn))+ -> (DocLoc, HsDoc GhcRn)+ -> UniqMap Name (IntMap (HsDoc GhcRn)) args acc ((ArgDoc name i), s) = -- Insert the doc for the arg into the argument map for the function. This -- means we have to search to see if an map already exists for the -- function, and insert the new argument if it exists, or create a new map- let ds = mkHsDocString s- in M.insertWith (\_ m -> IM.insert i ds m) name (IM.singleton i ds) acc+ addToUniqMap_C (\_ m -> IM.insert i s m) acc name (IM.singleton i s) args acc _ = acc -- | Unions together two 'ArgDocMaps' (or ArgMaps in haddock-api), such that two -- maps with values for the same key merge the inner map as well. -- Left biased so @unionArgMaps a b@ prefers @a@ over @b@.-unionArgMaps :: Map Name (IntMap b)- -> Map Name (IntMap b)- -> Map Name (IntMap b)-unionArgMaps a b = M.foldlWithKey go b a++unionArgMaps :: forall b . UniqMap Name (IntMap b)+ -> UniqMap Name (IntMap b)+ -> UniqMap Name (IntMap b)+unionArgMaps a b = nonDetFoldUniqMap go b a where- go acc n newArgMap- | Just oldArgMap <- M.lookup n acc =- M.insert n (newArgMap `IM.union` oldArgMap) acc- | otherwise = M.insert n newArgMap acc+ go :: (Name, IntMap b)+ -> UniqMap Name (IntMap b) -> UniqMap Name (IntMap b)+ go (n, newArgMap) acc+ | Just oldArgMap <- lookupUniqMap acc n =+ addToUniqMap acc n (newArgMap `IM.union` oldArgMap)+ | otherwise = addToUniqMap acc n newArgMap
compiler/GHC/HsToCore/Expr.hs view
@@ -143,7 +143,7 @@ ; dsUnliftedBind bind body } where- is_polymorphic (AbsBinds { abs_tvs = tvs, abs_ev_vars = evs })+ is_polymorphic (XHsBindsLR (AbsBinds { abs_tvs = tvs, abs_ev_vars = evs })) = not (null tvs && null evs) is_polymorphic _ = False @@ -161,6 +161,7 @@ ; (force_vars,prs) <- dsLHsBinds binds ; let body' = foldr seqVar body force_vars ; assertPpr (not (any (isUnliftedType . idType . fst) prs)) (ppr is_rec $$ ppr binds) $+ -- NB: bindings have a fixed RuntimeRep, so it's OK to call isUnliftedType case prs of [] -> return body _ -> return (Let (Rec prs) body') }@@ -177,10 +178,10 @@ ------------------ dsUnliftedBind :: HsBind GhcTc -> CoreExpr -> DsM CoreExpr-dsUnliftedBind (AbsBinds { abs_tvs = [], abs_ev_vars = []- , abs_exports = exports- , abs_ev_binds = ev_binds- , abs_binds = lbinds }) body+dsUnliftedBind (XHsBindsLR (AbsBinds { abs_tvs = [], abs_ev_vars = []+ , abs_exports = exports+ , abs_ev_binds = ev_binds+ , abs_binds = lbinds })) body = do { let body1 = foldr bind_export body exports bind_export export b = bindNonRec (abe_poly export) (Var (abe_mono export)) b ; body2 <- foldlM (\body lbind -> dsUnliftedBind (unLoc lbind) body)@@ -745,10 +746,11 @@ -- Here is where we desugar the Template Haskell brackets and escapes -- Template Haskell stuff+-- See Note [The life cycle of a TH quotation] -dsExpr (HsRnBracketOut x _ _) = dataConCantHappen x-dsExpr (HsTcBracketOut _ hs_wrapper x ps) = dsBracket hs_wrapper x ps-dsExpr (HsSpliceE _ s) = pprPanic "dsExpr:splice" (ppr s)+dsExpr (HsTypedBracket (HsBracketTc q _ hs_wrapper ps) _) = dsBracket hs_wrapper q ps+dsExpr (HsUntypedBracket (HsBracketTc q _ hs_wrapper ps) _) = dsBracket hs_wrapper q ps+dsExpr (HsSpliceE _ s) = pprPanic "dsExpr:splice" (ppr s) -- Arrow notation extension dsExpr (HsProc _ pat cmd) = dsProcExpr pat cmd@@ -761,7 +763,6 @@ dsExpr (OpApp x _ _ _) = dataConCantHappen x dsExpr (SectionL x _ _) = dataConCantHappen x dsExpr (SectionR x _ _) = dataConCantHappen x-dsExpr (HsBracket x _) = dataConCantHappen x ds_prag_expr :: HsPragE GhcTc -> LHsExpr GhcTc -> DsM CoreExpr ds_prag_expr (HsPragSCC _ _ cc) expr = do
compiler/GHC/HsToCore/Foreign/Decl.hs view
@@ -43,6 +43,7 @@ import GHC.Cmm.Expr import GHC.Cmm.Utils+import GHC.Cmm.CLabel import GHC.Driver.Ppr import GHC.Types.ForeignCall import GHC.Builtin.Types@@ -95,11 +96,12 @@ = return (NoStubs, nilOL) dsForeigns' fos = do mod <- getModule+ platform <- targetPlatform <$> getDynFlags fives <- mapM do_ldecl fos let (hs, cs, idss, bindss) = unzip4 fives fe_ids = concat idss- fe_init_code = foreignExportsInitialiser mod fe_ids+ fe_init_code = foreignExportsInitialiser platform mod fe_ids -- return (ForeignStubs (mconcat hs)@@ -298,7 +300,7 @@ simpl_opts wrap_rhs' - return ([(work_id, work_rhs), (fn_id_w_inl, wrap_rhs')], mempty, CStub cDoc)+ return ([(work_id, work_rhs), (fn_id_w_inl, wrap_rhs')], mempty, CStub cDoc [] []) {- ************************************************************************@@ -526,7 +528,9 @@ Int -- total size of arguments ) mkFExportCBits dflags c_nm maybe_target arg_htys res_hty is_IO_res_ty cc- = (header_bits, c_bits, type_string,+ = ( header_bits+ , CStub body [] []+ , type_string, sum [ widthInBytes (typeWidth rep) | (_,_,_,rep) <- aug_arg_info] -- all the args -- NB. the calculation here isn't strictly speaking correct. -- We have a primitive Haskell type (eg. Int#, Double#), and@@ -646,7 +650,7 @@ -- finally, the whole darn thing- c_bits = CStub $+ body = space $$ extern_decl $$ fun_proto $$@@ -682,10 +686,9 @@ , rbrace ] --foreignExportsInitialiser :: Module -> [Id] -> CStub-foreignExportsInitialiser _ [] = mempty-foreignExportsInitialiser mod hs_fns =+foreignExportsInitialiser :: Platform -> Module -> [Id] -> CStub+foreignExportsInitialiser _ _ [] = mempty+foreignExportsInitialiser platform mod hs_fns = -- Initialise foreign exports by registering a stable pointer from an -- __attribute__((constructor)) function. -- The alternative is to do this from stginit functions generated in@@ -696,21 +699,18 @@ -- (this is bad for big umbrella modules like Graphics.Rendering.OpenGL) -- -- See Note [Tracking foreign exports] in rts/ForeignExports.c- CStub $ vcat- [ text "static struct ForeignExportsList" <+> list_symbol <+> equals+ initializerCStub platform fn_nm list_decl fn_body+ where+ fn_nm = mkInitializerStubLabel mod "fexports"+ mod_str = pprModuleName (moduleName mod)+ fn_body = text "registerForeignExports" <> parens (char '&' <> list_symbol) <> semi+ list_symbol = text "stg_exports_" <> mod_str+ list_decl = text "static struct ForeignExportsList" <+> list_symbol <+> equals <+> braces ( text ".exports = " <+> export_list <> comma <+> text ".n_entries = " <+> ppr (length hs_fns)) <> semi- , text "static void " <> ctor_symbol <> text "(void)"- <+> text " __attribute__((constructor));"- , text "static void " <> ctor_symbol <> text "()"- , braces (text "registerForeignExports" <> parens (char '&' <> list_symbol) <> semi)- ]- where- mod_str = pprModuleName (moduleName mod)- ctor_symbol = text "stginit_export_" <> mod_str- list_symbol = text "stg_exports_" <> mod_str+ export_list = braces $ pprWithCommas closure_ptr hs_fns closure_ptr :: Id -> SDoc@@ -820,6 +820,8 @@ Just (_, _, data_con, [Scaled _ prim_ty]) -> assert (dataConSourceArity data_con == 1) $ assertPpr (isUnliftedType prim_ty) (ppr prim_ty)+ -- NB: it's OK to call isUnliftedType here, as we don't allow+ -- representation-polymorphic types in foreign import/export declarations prim_ty _other -> pprPanic "GHC.HsToCore.Foreign.Decl.getPrimTyOf" (ppr ty) where
compiler/GHC/HsToCore/Match.hs view
@@ -450,6 +450,7 @@ -- Doing this check during type-checking is unsatisfactory because we may -- not fully know the zonked types yet. We sure do here. = do { let unlifted_bndrs = filter (isUnliftedType . idType) (collectPatBinders CollNoDictBinders pat)+ -- NB: the binders can't be representation-polymorphic, so we're OK to call isUnliftedType ; unless (null unlifted_bndrs) $ putSrcSpanDs (getLocA pat) $ diagnosticDs (DsLazyPatCantBindVarsOfUnliftedType unlifted_bndrs)
compiler/GHC/HsToCore/Match/Literal.hs view
@@ -506,9 +506,9 @@ tidyLitPat :: HsLit GhcTc -> Pat GhcTc -- Result has only the following HsLits:--- HsIntPrim, HsWordPrim, HsCharPrim, HsFloatPrim--- HsDoublePrim, HsStringPrim, HsString--- * HsInteger, HsRat, HsInt can't show up in LitPats+-- HsIntPrim, HsWordPrim, HsCharPrim, HsString+-- * HsInteger, HsRat, HsInt, as well as HsStringPrim,+-- HsFloatPrim and HsDoublePrim can't show up in LitPats -- * We get rid of HsChar right here tidyLitPat (HsChar src c) = unLoc (mkCharLitPat src c) tidyLitPat (HsString src s)
compiler/GHC/HsToCore/Pmc/Desugar.hs view
@@ -388,12 +388,13 @@ , GRHSs{grhssGRHSs = [L _ (GRHS _ _grds rhs)]} <- grhss = do core_rhs <- dsLExpr rhs return [PmLet x core_rhs]- go (L _ AbsBinds{ abs_tvs = [], abs_ev_vars = []- , abs_exports=exports, abs_binds = binds }) = do+ go (L _ (XHsBindsLR (AbsBinds+ { abs_tvs = [], abs_ev_vars = []+ , abs_exports=exports, abs_binds = binds }))) = do -- Typechecked HsLocalBinds are wrapped in AbsBinds, which carry -- renamings. See Note [Long-distance information for HsLocalBinds] -- for the details.- let go_export :: ABExport GhcTc -> Maybe PmGrd+ let go_export :: ABExport -> Maybe PmGrd go_export ABE{abe_poly = x, abe_mono = y, abe_wrap = wrap} | isIdHsWrapper wrap = assertPpr (idType x `eqType` idType y)
compiler/GHC/HsToCore/Pmc/Solver.hs view
@@ -46,6 +46,7 @@ import GHC.Utils.Panic import GHC.Utils.Panic.Plain import GHC.Data.Bag+import GHC.Types.Basic (Levity(..)) import GHC.Types.CompleteMatch import GHC.Types.Unique.Set import GHC.Types.Unique.DSet@@ -146,7 +147,7 @@ -- Ex.: @vanillaCompleteMatchTC 'Maybe' ==> Just ("Maybe", {'Just','Nothing'})@ vanillaCompleteMatchTC :: TyCon -> Maybe CompleteMatch vanillaCompleteMatchTC tc =- let -- | TYPE acts like an empty data type on the term-level (#14086), but+ let -- TYPE acts like an empty data type on the term-level (#14086), but -- it is a PrimTyCon, so tyConDataCons_maybe returns Nothing. Hence a -- special case. mb_dcs | tc == tYPETyCon = Just []@@ -172,7 +173,7 @@ addTyConMatches :: TyCon -> ResidualCompleteMatches -> DsM ResidualCompleteMatches addTyConMatches tc rcm = add_tc_match <$> addCompleteMatches rcm where- -- | Add the vanilla COMPLETE set from the data defn, if any. But only if+ -- Add the vanilla COMPLETE set from the data defn, if any. But only if -- it's not already present. add_tc_match rcm = rcm{rcm_vanilla = rcm_vanilla rcm <|> vanillaCompleteMatchTC tc}@@ -674,7 +675,7 @@ filterUnliftedFields :: PmAltCon -> [Id] -> [Id] filterUnliftedFields con args = [ arg | (arg, bang) <- zipEqual "addPhiCt" args (pmAltConImplBangs con)- , isBanged bang || isUnliftedType (idType arg) ]+ , isBanged bang || typeLevity_maybe (idType arg) == Just Unlifted ] -- | Adds the constraint @x ~ ⊥@, e.g. that evaluation of a particular 'Id' @x@ -- surely diverges. Quite similar to 'addConCt', only that it only cares about@@ -685,11 +686,12 @@ case bot of IsNotBot -> mzero -- There was x ≁ ⊥. Contradiction! IsBot -> pure nabla -- There already is x ~ ⊥. Nothing left to do- MaybeBot -> -- We add x ~ ⊥+ MaybeBot -- We add x ~ ⊥+ | Just Unlifted <- typeLevity_maybe (idType x) -- Case (3) in Note [Strict fields and variables of unlifted type]- if isUnliftedType (idType x)- then mzero -- unlifted vars can never be ⊥- else do+ -> mzero -- unlifted vars can never be ⊥+ | otherwise+ -> do let vi' = vi{ vi_bot = IsBot } pure nabla{ nabla_tm_st = ts{ts_facts = addToUSDFM env y vi' } } @@ -720,7 +722,7 @@ Just x -> markDirty x nabla' Nothing -> nabla' where- -- | Update `x`'s 'VarInfo' entry. Fail ('MaybeT') if contradiction,+ -- Update `x`'s 'VarInfo' entry. Fail ('MaybeT') if contradiction, -- otherwise return updated entry and `Just x'` if `x` should be marked dirty, -- where `x'` is the representative of `x`. go :: VarInfo -> MaybeT DsM (Maybe Id, VarInfo)@@ -844,7 +846,7 @@ -- lift $ tracePm "addCoreCt" (ppr x <+> dcolon <+> ppr (idType x) $$ ppr e $$ ppr e') execStateT (core_expr x e') nabla where- -- | Takes apart a 'CoreExpr' and tries to extract as much information about+ -- Takes apart a 'CoreExpr' and tries to extract as much information about -- literals and constructor applications as possible. core_expr :: Id -> CoreExpr -> StateT Nabla (MaybeT DsM) () -- TODO: Handle newtypes properly, by wrapping the expression in a DataCon@@ -885,7 +887,7 @@ -- up substituting inside a forall or lambda (i.e. seldom) -- so using exprFreeVars seems fine. See MR !1647. - -- | The @e@ in @let x = e@ had no familiar form. But we can still see if+ -- The @e@ in @let x = e@ had no familiar form. But we can still see if -- see if we already encountered a constraint @let y = e'@ with @e'@ -- semantically equivalent to @e@, in which case we may add the constraint -- @x ~ y@.@@ -901,7 +903,7 @@ core_expr x e pure x - -- | Look at @let x = K taus theta es@ and generate the following+ -- Look at @let x = K taus theta es@ and generate the following -- constraints (assuming universals were dropped from @taus@ before): -- 1. @x ≁ ⊥@ if 'K' is not a Newtype constructor. -- 2. @a_1 ~ tau_1, ..., a_n ~ tau_n@ for fresh @a_i@@@ -928,7 +930,7 @@ -- 4. @x ~ K as ys@ pm_alt_con_app x (PmAltConLike (RealDataCon dc)) ex_tvs arg_ids - -- | Adds a literal constraint, i.e. @x ~ 42@.+ -- Adds a literal constraint, i.e. @x ~ 42@. -- Also we assume that literal expressions won't diverge, so this -- will add a @x ~/ ⊥@ constraint. pm_lit :: Id -> PmLit -> StateT Nabla (MaybeT DsM) ()@@ -936,7 +938,7 @@ modifyT $ \nabla -> addNotBotCt nabla x pm_alt_con_app x (PmAltLit lit) [] [] - -- | Adds the given constructor application as a solution for @x@.+ -- Adds the given constructor application as a solution for @x@. pm_alt_con_app :: Id -> PmAltCon -> [TyVar] -> [Id] -> StateT Nabla (MaybeT DsM) () pm_alt_con_app x con tvs args = modifyT $ \nabla -> addConCt nabla x con tvs args @@ -1355,15 +1357,13 @@ isDataConTriviallyInhabited dc | isTyConTriviallyInhabited (dataConTyCon dc) = True isDataConTriviallyInhabited dc =- null (dataConTheta dc) && -- (1)- null (dataConImplBangs dc) && -- (2)- null (dataConUnliftedFieldTys dc) -- (3)+ null (dataConTheta dc) && -- (1)+ null (dataConImplBangs dc) && -- (2)+ null (dataConMightBeUnliftedFieldTys dc) -- (3) -dataConUnliftedFieldTys :: DataCon -> [Type]-dataConUnliftedFieldTys =- -- A representation-polymorphic field requires an inhabitation test, hence compare to- -- @Just True@- filter ((== Just True) . isLiftedType_maybe) . map scaledThing . dataConOrigArgTys+dataConMightBeUnliftedFieldTys :: DataCon -> [Type]+dataConMightBeUnliftedFieldTys =+ filter mightBeUnliftedType . map scaledThing . dataConOrigArgTys isTyConTriviallyInhabited :: TyCon -> Bool isTyConTriviallyInhabited tc = elementOfUniqSet (getUnique tc) triviallyInhabitedTyConKeys@@ -1401,7 +1401,7 @@ -- the unlikely bogus case of an unlifted field that has a bang. unlifted_or_strict_fields :: DataCon -> Int unlifted_or_strict_fields dc = fast_length (dataConImplBangs dc)- + fast_length (dataConUnliftedFieldTys dc)+ + fast_length (dataConMightBeUnliftedFieldTys dc) -- | @instCon fuel nabla (x::match_ty) K@ tries to instantiate @x@ to @K@ by -- adding the proper constructor constraint.@@ -1836,7 +1836,7 @@ | otherwise -> generateInhabitingPatterns mode xs n nabla where- -- | Tries to instantiate a variable by possibly following the chain of+ -- Tries to instantiate a variable by possibly following the chain of -- newtypes and then instantiating to all ConLikes of the wrapped type's -- minimal residual COMPLETE set. try_instantiate :: Id -> [Id] -> Int -> Nabla -> DsM [Nabla]@@ -1868,7 +1868,7 @@ then generateInhabitingPatterns mode xs n newty_nabla -- bot is still possible. Display a wildcard! else pure nablas' - -- | Instantiates a chain of newtypes, beginning at @x@.+ -- Instantiates a chain of newtypes, beginning at @x@. -- Turns @x nabla [T,U,V]@ to @(y, nabla')@, where @nabla'@ we has the fact -- @x ~ T (U (V y))@. instantiate_newtype_chain :: Id -> Nabla -> [(Type, DataCon, Type)] -> MaybeT DsM (Id, Nabla)
compiler/GHC/HsToCore/Quote.hs view
@@ -158,7 +158,7 @@ ----------------------------------------------------------------------------- dsBracket :: Maybe QuoteWrapper -- ^ This is Nothing only when we are dealing with a VarBr- -> HsBracket GhcRn+ -> HsQuote GhcRn -- See Note [The life cycle of a TH quotation] -> [PendingTcSplice] -> DsM CoreExpr -- See Note [Desugaring Brackets]@@ -168,7 +168,6 @@ dsBracket wrap brack splices = do_brack brack- where runOverloaded act = do -- In the overloaded case we have to get given a wrapper, it is just@@ -177,7 +176,6 @@ mw <- mkMetaWrappers (expectJust "runOverloaded" wrap) runReaderT (mapReaderT (dsExtendMetaEnv new_bit) act) mw - new_bit = mkNameEnv [(n, DsSplice (unLoc e)) | PendingTcSplice n e <- splices] @@ -186,9 +184,9 @@ do_brack (PatBr _ p) = runOverloaded $ do { MkC p1 <- repTopP p ; return p1 } do_brack (TypBr _ t) = runOverloaded $ do { MkC t1 <- repLTy t ; return t1 } do_brack (DecBrG _ gp) = runOverloaded $ do { MkC ds1 <- repTopDs gp ; return ds1 }- do_brack (DecBrL {}) = panic "dsBracket: unexpected DecBrL"- do_brack (TExpBr _ e) = runOverloaded $ do { MkC e1 <- repLE e ; return e1 }+ do_brack (DecBrL {}) = panic "dsUntypedBracket: unexpected DecBrL" + {- Note [Desugaring Brackets] ~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -1120,6 +1118,7 @@ repInline :: InlineSpec -> MetaM (Core TH.Inline) repInline (NoInline _ ) = dataCon noInlineDataConName+repInline (Opaque _ ) = dataCon opaqueDataConName repInline (Inline _ ) = dataCon inlineDataConName repInline (Inlinable _ ) = dataCon inlinableDataConName repInline NoUserInlinePrag = notHandled ThNoUserInline@@ -1636,9 +1635,8 @@ then repE ds_expr else repE orig_expr } repE e@(HsPragE _ (HsPragSCC {}) _) = notHandled (ThCostCentres e)-repE e@(HsBracket{}) = notHandled (ThExpressionForm e)-repE e@(HsRnBracketOut{}) = notHandled (ThExpressionForm e)-repE e@(HsTcBracketOut{}) = notHandled (ThExpressionForm e)+repE e@(HsTypedBracket{}) = notHandled (ThExpressionForm e)+repE e@(HsUntypedBracket{}) = notHandled (ThExpressionForm e) repE e@(HsProc{}) = notHandled (ThExpressionForm e) {- Note [Quotation and rebindable syntax]@@ -1911,7 +1909,6 @@ ; ans <- repVal patcore x empty_decls ; return (srcLocSpan (getSrcLoc v), ans) } -rep_bind (L _ (AbsBinds {})) = panic "rep_bind: AbsBinds" rep_bind (L loc (PatSynBind _ (PSB { psb_id = syn , psb_args = args , psb_def = pat@@ -2078,7 +2075,14 @@ repP (NPat _ (L _ l) Nothing _) = do { a <- repOverloadedLiteral l ; repPlit a } repP (ViewPat _ e p) = do { e' <- repLE e; p' <- repLP p; repPview e' p' }-repP p@(NPat _ _ (Just _) _) = notHandled (ThNegativeOverloadedPatterns p)+repP p@(NPat _ (L _ l) (Just _) _)+ | OverLitRn rebindable _ <- ol_ext l+ , rebindable = notHandled (ThNegativeOverloadedPatterns p)+ | HsIntegral i <- ol_val l = do { a <- repOverloadedLiteral l{ol_val = HsIntegral (negateIntegralLit i)}+ ; repPlit a }+ | HsFractional i <- ol_val l = do { a <- repOverloadedLiteral l{ol_val = HsFractional (negateFractionalLit i)}+ ; repPlit a }+ | otherwise = notHandled (ThExoticPattern p) repP (SigPat _ p t) = do { p' <- repLP p ; t' <- repLTy (hsPatSigType t) ; repPsig p' t' }
compiler/GHC/HsToCore/Types.hs view
@@ -85,7 +85,7 @@ -- The Id has type THSyntax.Var | DsSplice (HsExpr GhcTc) -- These bindings are introduced by- -- the PendingSplices on a HsBracketOut+ -- the PendingSplices on a Hs*Bracket -- | Desugaring monad. See also 'TcM'. type DsM = TcRnIf DsGblEnv DsLclEnv
compiler/GHC/Iface/Ext/Ast.hs view
@@ -205,7 +205,7 @@ -- These synonyms match those defined in compiler/GHC.hs type RenamedSource = ( HsGroup GhcRn, [LImportDecl GhcRn] , Maybe [(LIE GhcRn, Avails)]- , Maybe LHsDocString )+ , Maybe (LHsDoc GhcRn) ) type TypecheckedSource = LHsBinds GhcTc @@ -267,12 +267,11 @@ addSubstitution mono poly hs = hs{name_remapping = extendNameEnv (name_remapping hs) (varName mono) poly} -modifyState :: ModifyState (IdP p) => [ABExport p] -> HieState -> HieState+modifyState :: [ABExport] -> HieState -> HieState modifyState = foldr go id where go ABE{abe_poly=poly,abe_mono=mono} f = addSubstitution mono poly . f- go _ f = f type HieM = ReaderT NodeOrigin (State HieState) @@ -317,12 +316,13 @@ enrichHie :: TypecheckedSource -> RenamedSource -> Bag EvBind -> [ClsInst] -> [TyCon] -> HieASTs Type-enrichHie ts (hsGrp, imports, exports, _) ev_bs insts tcs =+enrichHie ts (hsGrp, imports, exports, docs) ev_bs insts tcs = runIdentity $ flip evalStateT initState $ flip runReaderT SourceInfo $ do tasts <- toHie $ fmap (BC RegularBind ModuleScope) ts rasts <- processGrp hsGrp imps <- toHie $ filter (not . ideclImplicit . unLoc) imports exps <- toHie $ fmap (map $ IEC Export . fst) exports+ docs <- toHie docs -- Add Instance bindings forM_ insts $ \i -> addUnlocatedEvBind (is_dfun i) (EvidenceVarBind (EvInstBind False (is_cls_nm i)) ModuleScope Nothing)@@ -342,6 +342,7 @@ , rasts , imps , exps+ , docs ] modulify (HiePath file) xs' = do@@ -388,6 +389,7 @@ , toHie $ hs_warnds grp , toHie $ hs_annds grp , toHie $ hs_ruleds grp+ , toHie $ hs_docs grp ] getRealSpanA :: SrcSpanAnn' ann -> Maybe Span@@ -723,7 +725,7 @@ fallback :: HieM [HieAST Type] fallback = makeNodeA e spn - -- | Skip computing the type of some expressions for performance reasons.+ -- Skip computing the type of some expressions for performance reasons. -- -- See impact on Haddock output (esp. missing type annotations or links) -- before skipping more kinds of expressions. See impact on Haddock@@ -847,21 +849,27 @@ VarBind{var_rhs = expr} -> [ toHie expr ]- AbsBinds{ abs_exports = xs, abs_binds = binds- , abs_ev_binds = ev_binds- , abs_ev_vars = ev_vars } ->- [ lift (modify (modifyState xs)) >> -- Note [Name Remapping]- (toHie $ fmap (BC context scope) binds)- , toHie $ map (L span . abe_wrap) xs- , toHie $- map (EvBindContext (mkScopeA span) (getRealSpanA span)- . L span) ev_binds- , toHie $- map (C (EvidenceVarBind EvSigBind- (mkScopeA span)- (getRealSpanA span))- . L span) ev_vars- ]+ XHsBindsLR ext -> case hiePass @p of+#if __GLASGOW_HASKELL__ < 811+ HieRn -> dataConCantHappen ext+#endif+ HieTc+ | AbsBinds{ abs_exports = xs, abs_binds = binds+ , abs_ev_binds = ev_binds+ , abs_ev_vars = ev_vars } <- ext+ ->+ [ lift (modify (modifyState xs)) >> -- Note [Name Remapping]+ (toHie $ fmap (BC context scope) binds)+ , toHie $ map (L span . abe_wrap) xs+ , toHie $+ map (EvBindContext (mkScopeA span) (getRealSpanA span)+ . L span) ev_binds+ , toHie $+ map (C (EvidenceVarBind EvSigBind+ (mkScopeA span)+ (getRealSpanA span))+ . L span) ev_vars+ ] PatSynBind _ psb -> [ toHie $ L (locA span) psb -- PatSynBinds only occur at the top level ]@@ -1178,17 +1186,23 @@ HsStatic _ expr -> [ toHie expr ]- HsBracket _ b ->- [ toHie b- ]- HsRnBracketOut _ b p ->- [ toHie b- , toHie p- ]- HsTcBracketOut _ _wrap b p ->- [ toHie b- , toHie p- ]+ HsTypedBracket xbracket b -> case hiePass @p of+ HieRn ->+ [ toHie b+ ]+ HieTc | HsBracketTc _ _ _ p <- xbracket ->+ [ toHie b+ , toHie p+ ]+ HsUntypedBracket xbracket b -> case hiePass @p of+ HieRn ->+ [ toHie b+ , toHie xbracket+ ]+ HieTc | HsBracketTc _ _ _ p <- xbracket ->+ [ toHie b+ , toHie p+ ] HsSpliceE _ x -> [ toHie $ L mspan x ]@@ -1585,7 +1599,8 @@ instance ToHie (LocatedA (ConDecl GhcRn)) where toHie (L span decl) = concatM $ makeNode decl (locA span) : case decl of ConDeclGADT { con_names = names, con_bndrs = L outer_bndrs_loc outer_bndrs- , con_mb_cxt = ctx, con_g_args = args, con_res_ty = typ } ->+ , con_mb_cxt = ctx, con_g_args = args, con_res_ty = typ+ , con_doc = doc} -> [ toHie $ map (C (Decl ConDec $ getRealSpanA span)) names , case outer_bndrs of HsOuterImplicit{hso_ximplicit = imp_vars} ->@@ -1596,6 +1611,7 @@ , toHie ctx , toHie args , toHie typ+ , toHie doc ] where rhsScope = combineScopes argsScope tyScope@@ -1606,11 +1622,13 @@ tyScope = mkLScopeA typ resScope = ResolvedScopes [ctxScope, rhsScope] ConDeclH98 { con_name = name, con_ex_tvs = qvars- , con_mb_cxt = ctx, con_args = dets } ->+ , con_mb_cxt = ctx, con_args = dets+ , con_doc = doc} -> [ toHie $ C (Decl ConDec $ getRealSpan (locA span)) name , toHie $ tvScopes (ResolvedScopes []) rhsScope qvars , toHie ctx , toHie dets+ , toHie doc ] where rhsScope = combineScopes ctxScope argsScope@@ -1769,8 +1787,9 @@ HsSpliceTy _ a -> [ toHie $ L span a ]- HsDocTy _ a _ ->+ HsDocTy _ a doc -> [ toHie a+ , toHie doc ] HsBangTy _ _ ty -> [ toHie ty@@ -1821,9 +1840,10 @@ instance ToHie (LocatedA (ConDeclField GhcRn)) where toHie (L span field) = concatM $ makeNode field (locA span) : case field of- ConDeclField _ fields typ _ ->+ ConDeclField _ fields typ doc -> [ toHie $ map (RFC RecFieldDecl (getRealSpan $ loc typ)) fields , toHie typ+ , toHie doc ] instance ToHie (LHsExpr a) => ToHie (ArithSeqInfo a) where@@ -1848,7 +1868,7 @@ [ toHie splice ] -instance ToHie (HsBracket a) where+instance ToHie (HsQuote a) where toHie _ = pure [] instance ToHie PendingRnSplice where@@ -2077,8 +2097,8 @@ IEModuleContents _ n -> [ toHie $ IEC c n ]- IEGroup _ _ _ -> []- IEDoc _ _ -> []+ IEGroup _ _ d -> [toHie d]+ IEDoc _ d -> [toHie d] IEDocNamed _ _ -> [] instance ToHie (IEContext (LIEWrappedName Name)) where@@ -2098,3 +2118,13 @@ [ makeNode lbl span , toHie $ C (IEThing c) $ L span (flSelector lbl) ]++instance ToHie (LocatedA (DocDecl GhcRn)) where+ toHie (L span d) = concatM $ makeNodeA d span : case d of+ DocCommentNext d -> [ toHie d ]+ DocCommentPrev d -> [ toHie d ]+ DocCommentNamed _ d -> [ toHie d ]+ DocGroup _ d -> [ toHie d ]++instance ToHie (LHsDoc GhcRn) where+ toHie (L span d@(WithHsDocIdentifiers _ ids)) = concatM $ makeNode d span : [toHie $ map (C Use) ids]
compiler/GHC/Iface/Load.hs view
@@ -21,7 +21,7 @@ -- RnM/TcM functions loadModuleInterface, loadModuleInterfaces, loadSrcInterface, loadSrcInterface_maybe,- loadInterfaceForName, loadInterfaceForNameMaybe, loadInterfaceForModule,+ loadInterfaceForName, loadInterfaceForModule, -- IfM functions loadInterface,@@ -349,15 +349,6 @@ ; assertPpr (isExternalName name) (ppr name) $ initIfaceTcRn $ loadSysInterface doc (nameModule name) } --- | Only loads the interface for external non-local names.-loadInterfaceForNameMaybe :: SDoc -> Name -> TcRn (Maybe ModIface)-loadInterfaceForNameMaybe doc name- = do { this_mod <- getModule- ; if nameIsLocalOrFrom this_mod name || not (isExternalName name)- then return Nothing- else Just <$> (initIfaceTcRn $ loadSysInterface doc (nameModule name))- }- -- | Loads the interface for a given Module. loadInterfaceForModule :: SDoc -> Module -> TcRn ModIface loadInterfaceForModule doc m@@ -1025,7 +1016,7 @@ mi_decls = [], mi_fixities = fixities, mi_final_exts = (mi_final_exts empty_iface){ mi_fix_fn = mkIfaceFixCache fixities },- mi_decl_docs = ghcPrimDeclDocs -- See Note [GHC.Prim Docs]+ mi_docs = Just ghcPrimDeclDocs -- See Note [GHC.Prim Docs] } where empty_iface = emptyFullModIface gHC_PRIM@@ -1142,9 +1133,7 @@ , pprTrustInfo (mi_trust iface) , pprTrustPkg (mi_trust_pkg iface) , vcat (map ppr (mi_complete_matches iface))- , text "module header:" $$ nest 2 (ppr (mi_doc_hdr iface))- , text "declaration docs:" $$ nest 2 (ppr (mi_decl_docs iface))- , text "arg docs:" $$ nest 2 (ppr (mi_arg_docs iface))+ , text "docs:" $$ nest 2 (ppr (mi_docs iface)) , text "extensible fields:" $$ nest 2 (pprExtensibleFields (mi_ext_fields iface)) ] where@@ -1209,13 +1198,13 @@ pprTrustPkg :: Bool -> SDoc pprTrustPkg tpkg = text "require own pkg trusted:" <+> ppr tpkg -instance Outputable Warnings where+instance Outputable (Warnings pass) where ppr = pprWarns -pprWarns :: Warnings -> SDoc+pprWarns :: Warnings pass -> SDoc pprWarns NoWarnings = Outputable.empty pprWarns (WarnAll txt) = text "Warn all" <+> ppr txt-pprWarns (WarnSome prs) = text "Warnings"+pprWarns (WarnSome prs) = text "Warnings:" <+> vcat (map pprWarning prs) where pprWarning (name, txt) = ppr name <+> ppr txt
compiler/GHC/Iface/Make.hs view
@@ -125,12 +125,10 @@ , mg_hpc_info = hpc_info , mg_safe_haskell = safe_mode , mg_trust_pkg = self_trust- , mg_doc_hdr = doc_hdr- , mg_decl_docs = decl_docs- , mg_arg_docs = arg_docs+ , mg_docs = docs } = mkIface_ hsc_env this_mod hsc_src used_th deps rdr_env fix_env warns hpc_info self_trust- safe_mode usages doc_hdr decl_docs arg_docs mod_summary mod_details+ safe_mode usages docs mod_summary mod_details -- | Fully instantiate an interface. Adds fingerprints and potentially code -- generator produced information.@@ -222,34 +220,32 @@ usages <- mkUsageInfo hsc_env this_mod (imp_mods imports) used_names dep_files merged needed_links needed_pkgs - (doc_hdr', doc_map, arg_map) <- extractDocs tc_result+ docs <- extractDocs (ms_hspp_opts mod_summary) tc_result let partial_iface = mkIface_ hsc_env this_mod hsc_src used_th deps rdr_env fix_env warns hpc_info (imp_trust_own_pkg imports) safe_mode usages- doc_hdr' doc_map arg_map mod_summary+ docs mod_summary mod_details mkFullIface hsc_env partial_iface Nothing mkIface_ :: HscEnv -> Module -> HscSource -> Bool -> Dependencies -> GlobalRdrEnv- -> NameEnv FixItem -> Warnings -> HpcInfo+ -> NameEnv FixItem -> Warnings GhcRn -> HpcInfo -> Bool -> SafeHaskellMode -> [Usage]- -> Maybe HsDocString- -> DeclDocMap- -> ArgDocMap+ -> Maybe Docs -> ModSummary -> ModDetails -> PartialModIface mkIface_ hsc_env this_mod hsc_src used_th deps rdr_env fix_env src_warns hpc_info pkg_trust_req safe_mode usages- doc_hdr decl_docs arg_docs mod_summary+ docs mod_summary ModDetails{ md_insts = insts, md_fam_insts = fam_insts, md_rules = rules,@@ -322,9 +318,7 @@ mi_trust = trust_info, mi_trust_pkg = pkg_trust_req, mi_complete_matches = icomplete_matches,- mi_doc_hdr = doc_hdr,- mi_decl_docs = decl_docs,- mi_arg_docs = arg_docs,+ mi_docs = docs, mi_final_exts = (), mi_ext_fields = emptyExtensibleFields, mi_src_hash = ms_hs_hash mod_summary
compiler/GHC/Iface/Recomp.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE LambdaCase #-}
compiler/GHC/Iface/Recomp/Flags.hs view
@@ -28,9 +28,8 @@ -- the finger print on important fields in @DynFlags@ so that -- the recompilation checker can use this fingerprint. ----- NB: The 'Module' parameter is the 'Module' recorded by the--- *interface* file, not the actual 'Module' according to our--- 'DynFlags'.+-- NB: The 'Module' parameter is the 'Module' recorded by the *interface*+-- file, not the actual 'Module' according to our 'DynFlags'. fingerprintDynFlags :: HscEnv -> Module -> (BinHandle -> Name -> IO ()) -> IO Fingerprint@@ -43,7 +42,7 @@ safeHs = setSafeMode safeHaskell -- oflags = sort $ filter filterOFlags $ flags dflags - -- *all* the extension flags and the language+ -- all the extension flags and the language lang = (fmap fromEnum language, map fromEnum $ EnumSet.toList extensionFlags)
compiler/GHC/Iface/Tidy.hs view
@@ -6,21 +6,19 @@ {- (c) The GRASP/AQUA Project, Glasgow University, 1992-1998--\section{Tidying up Core} -} -module GHC.Iface.Tidy (- mkBootModDetailsTc, tidyProgram- ) where+-- | Tidying up Core+module GHC.Iface.Tidy+ ( TidyOpts (..)+ , UnfoldingExposure (..)+ , tidyProgram+ , mkBootModDetailsTc+ )+where import GHC.Prelude -import GHC.Driver.Session-import GHC.Driver.Backend-import GHC.Driver.Ppr-import GHC.Driver.Env- import GHC.Tc.Types import GHC.Tc.Utils.Env @@ -29,11 +27,7 @@ import GHC.Core.Unfold.Make import GHC.Core.FVs import GHC.Core.Tidy-import GHC.Core.Opt.Monad-import GHC.Core.Stats (coreBindsStats, CoreStats(..)) import GHC.Core.Seq (seqBinds)-import GHC.Core.Lint-import GHC.Core.Rules import GHC.Core.Opt.Arity ( exprArity, exprBotStrictness_maybe ) import GHC.Core.InstEnv import GHC.Core.Type ( tidyTopType )@@ -64,7 +58,6 @@ import GHC.Types.Name hiding (varName) import GHC.Types.Name.Set import GHC.Types.Name.Cache-import GHC.Types.Name.Ppr import GHC.Types.Avail import GHC.Types.Tickish import GHC.Types.TypeEnv@@ -80,7 +73,6 @@ import Data.Function import Data.List ( sortBy, mapAccumL ) import qualified Data.Set as S-import GHC.Platform.Ways import GHC.Types.CostCentre {-@@ -303,8 +295,7 @@ [Even non-exported things need system-wide Uniques because the byte-code generator builds a single Name->BCO symbol table.] - We use the NameCache kept in the HscEnv as the- source of such system-wide uniques.+ We use the given NameCache as the source of such system-wide uniques. For external Ids, use the original-name cache in the NameCache to ensure that the unique assigned is the same as the Id had@@ -348,145 +339,125 @@ load a compulsory unfolding -} -tidyProgram :: HscEnv -> ModGuts -> IO (CgGuts, ModDetails)-tidyProgram hsc_env (ModGuts { mg_module = mod- , mg_exports = exports- , mg_rdr_env = rdr_env- , mg_tcs = tcs- , mg_insts = cls_insts- , mg_fam_insts = fam_insts- , mg_binds = binds- , mg_patsyns = patsyns- , mg_rules = imp_rules- , mg_anns = anns- , mg_complete_matches = complete_matches- , mg_deps = deps- , mg_foreign = foreign_stubs- , mg_foreign_files = foreign_files- , mg_hpc_info = hpc_info- , mg_modBreaks = modBreaks- , mg_boot_exports = boot_exports- })-- = Err.withTiming logger- (text "CoreTidy"<+>brackets (ppr mod))- (const ()) $- do { let { omit_prags = gopt Opt_OmitInterfacePragmas dflags- ; expose_all = gopt Opt_ExposeAllUnfoldings dflags- ; print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) rdr_env- ; implicit_binds = concatMap getImplicitBinds tcs- }-- ; (unfold_env, tidy_occ_env)- <- chooseExternalIds hsc_env mod omit_prags expose_all- binds implicit_binds imp_rules- ; let { (trimmed_binds, trimmed_rules)- = findExternalRules omit_prags binds imp_rules unfold_env }+data UnfoldingExposure+ = ExposeNone -- ^ Don't expose unfoldings+ | ExposeSome -- ^ Only expose required unfoldings+ | ExposeAll -- ^ Expose all unfoldings+ deriving (Show,Eq,Ord) - ; let uf_opts = unfoldingOpts dflags- ; (tidy_env, tidy_binds)- <- tidyTopBinds uf_opts unfold_env boot_exports tidy_occ_env trimmed_binds+data TidyOpts = TidyOpts+ { opt_name_cache :: !NameCache+ , opt_collect_ccs :: !Bool+ , opt_unfolding_opts :: !UnfoldingOpts+ , opt_expose_unfoldings :: !UnfoldingExposure+ -- ^ Which unfoldings to expose+ , opt_trim_ids :: !Bool+ -- ^ trim off the arity, one-shot-ness, strictness etc which were+ -- retained for the benefit of the code generator+ , opt_expose_rules :: !Bool+ -- ^ Are rules exposed or not?+ , opt_static_ptr_opts :: !(Maybe StaticPtrOpts)+ -- ^ Options for generated static pointers, if enabled (/= Nothing).+ } - -- See Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable.- ; (spt_entries, tidy_binds') <-- sptCreateStaticBinds hsc_env mod tidy_binds- ; let { platform = targetPlatform (hsc_dflags hsc_env)- ; spt_init_code = sptModuleInitCode platform mod spt_entries- ; add_spt_init_code =- case backend dflags of- -- If we are compiling for the interpreter we will insert- -- any necessary SPT entries dynamically- Interpreter -> id- -- otherwise add a C stub to do so- _ -> (`appendStubC` spt_init_code)+tidyProgram :: TidyOpts -> ModGuts -> IO (CgGuts, ModDetails)+tidyProgram opts (ModGuts { mg_module = mod+ , mg_exports = exports+ , mg_tcs = tcs+ , mg_insts = cls_insts+ , mg_fam_insts = fam_insts+ , mg_binds = binds+ , mg_patsyns = patsyns+ , mg_rules = imp_rules+ , mg_anns = anns+ , mg_complete_matches = complete_matches+ , mg_deps = deps+ , mg_foreign = foreign_stubs+ , mg_foreign_files = foreign_files+ , mg_hpc_info = hpc_info+ , mg_modBreaks = modBreaks+ , mg_boot_exports = boot_exports+ }) = do - -- The completed type environment is gotten from- -- a) the types and classes defined here (plus implicit things)- -- b) adding Ids with correct IdInfo, including unfoldings,- -- gotten from the bindings- -- From (b) we keep only those Ids with External names;- -- the CoreTidy pass makes sure these are all and only- -- the externally-accessible ones- -- This truncates the type environment to include only the- -- exported Ids and things needed from them, which saves space- --- -- See Note [Don't attempt to trim data types]- ; final_ids = [ trimId omit_prags id- | id <- bindersOfBinds tidy_binds- , isExternalName (idName id)- , not (isWiredIn id)- ] -- See Note [Drop wired-in things]+ let implicit_binds = concatMap getImplicitBinds tcs - ; final_tcs = filterOut isWiredIn tcs- -- See Note [Drop wired-in things]- ; tidy_type_env = typeEnvFromEntities final_ids final_tcs patsyns fam_insts- ; tidy_cls_insts = mkFinalClsInsts tidy_type_env $ mkInstEnv cls_insts- ; tidy_rules = tidyRules tidy_env trimmed_rules+ (unfold_env, tidy_occ_env) <- chooseExternalIds opts mod binds implicit_binds imp_rules+ let (trimmed_binds, trimmed_rules) = findExternalRules opts binds imp_rules unfold_env - ; -- See Note [Injecting implicit bindings]- all_tidy_binds = implicit_binds ++ tidy_binds'+ let uf_opts = opt_unfolding_opts opts+ (tidy_env, tidy_binds) <- tidyTopBinds uf_opts unfold_env boot_exports tidy_occ_env trimmed_binds - -- Get the TyCons to generate code for. Careful! We must use- -- the untidied TyCons here, because we need- -- (a) implicit TyCons arising from types and classes defined- -- in this module- -- (b) wired-in TyCons, which are normally removed from the- -- TypeEnv we put in the ModDetails- -- (c) Constructors even if they are not exported (the- -- tidied TypeEnv has trimmed these away)- ; alg_tycons = filter isAlgTyCon tcs+ -- See Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable.+ (spt_entries, mcstub, tidy_binds') <- case opt_static_ptr_opts opts of+ Nothing -> pure ([], Nothing, tidy_binds)+ Just sopts -> sptCreateStaticBinds sopts mod tidy_binds + let all_foreign_stubs = case mcstub of+ Nothing -> foreign_stubs+ Just cstub -> foreign_stubs `appendStubC` cstub - ; local_ccs- | ways dflags `hasWay` WayProf- = collectCostCentres mod all_tidy_binds tidy_rules- | otherwise- = S.empty- }+ -- The completed type environment is gotten from+ -- a) the types and classes defined here (plus implicit things)+ -- b) adding Ids with correct IdInfo, including unfoldings,+ -- gotten from the bindings+ -- From (b) we keep only those Ids with External names;+ -- the CoreTidy pass makes sure these are all and only+ -- the externally-accessible ones+ -- This truncates the type environment to include only the+ -- exported Ids and things needed from them, which saves space+ --+ -- See Note [Don't attempt to trim data types]+ final_ids = [ trimId (opt_trim_ids opts) id+ | id <- bindersOfBinds tidy_binds+ , isExternalName (idName id)+ , not (isWiredIn id)+ ] -- See Note [Drop wired-in things] - ; endPassIO hsc_env print_unqual CoreTidy all_tidy_binds tidy_rules+ final_tcs = filterOut isWiredIn tcs+ -- See Note [Drop wired-in things]+ tidy_type_env = typeEnvFromEntities final_ids final_tcs patsyns fam_insts+ tidy_cls_insts = mkFinalClsInsts tidy_type_env $ mkInstEnv cls_insts+ tidy_rules = tidyRules tidy_env trimmed_rules - -- If the endPass didn't print the rules, but ddump-rules is- -- on, print now- ; unless (logHasDumpFlag logger Opt_D_dump_simpl) $- Logger.putDumpFileMaybe logger Opt_D_dump_rules- (showSDoc dflags (ppr CoreTidy <+> text "rules"))- FormatText- (pprRulesForUser tidy_rules)+ -- See Note [Injecting implicit bindings]+ all_tidy_binds = implicit_binds ++ tidy_binds' - -- Print one-line size info- ; let cs = coreBindsStats tidy_binds- ; Logger.putDumpFileMaybe logger Opt_D_dump_core_stats "Core Stats"- FormatText- (text "Tidy size (terms,types,coercions)"- <+> ppr (moduleName mod) <> colon- <+> int (cs_tm cs)- <+> int (cs_ty cs)- <+> int (cs_co cs) )+ -- Get the TyCons to generate code for. Careful! We must use+ -- the untidied TyCons here, because we need+ -- (a) implicit TyCons arising from types and classes defined+ -- in this module+ -- (b) wired-in TyCons, which are normally removed from the+ -- TypeEnv we put in the ModDetails+ -- (c) Constructors even if they are not exported (the+ -- tidied TypeEnv has trimmed these away)+ alg_tycons = filter isAlgTyCon tcs - ; return (CgGuts { cg_module = mod,- cg_tycons = alg_tycons,- cg_binds = all_tidy_binds,- cg_ccs = S.toList local_ccs,- cg_foreign = add_spt_init_code foreign_stubs,- cg_foreign_files = foreign_files,- cg_dep_pkgs = dep_direct_pkgs deps,- cg_hpc_info = hpc_info,- cg_modBreaks = modBreaks,- cg_spt_entries = spt_entries },+ local_ccs+ | opt_collect_ccs opts+ = collectCostCentres mod all_tidy_binds tidy_rules+ | otherwise+ = S.empty - ModDetails { md_types = tidy_type_env,- md_rules = tidy_rules,- md_insts = tidy_cls_insts,- md_fam_insts = fam_insts,- md_exports = exports,- md_anns = anns, -- are already tidy- md_complete_matches = complete_matches- })- }- where- dflags = hsc_dflags hsc_env- logger = hsc_logger hsc_env+ return (CgGuts { cg_module = mod+ , cg_tycons = alg_tycons+ , cg_binds = all_tidy_binds+ , cg_ccs = S.toList local_ccs+ , cg_foreign = all_foreign_stubs+ , cg_foreign_files = foreign_files+ , cg_dep_pkgs = dep_direct_pkgs deps+ , cg_hpc_info = hpc_info+ , cg_modBreaks = modBreaks+ , cg_spt_entries = spt_entries+ }+ , ModDetails { md_types = tidy_type_env+ , md_rules = tidy_rules+ , md_insts = tidy_cls_insts+ , md_fam_insts = fam_insts+ , md_exports = exports+ , md_anns = anns -- are already tidy+ , md_complete_matches = complete_matches+ }+ ) ------------------------------------------------------------------------------@@ -541,8 +512,8 @@ -- etc which tidyTopIdInfo retains for the benefit of the code generator -- but which we don't want in the interface file or ModIface for -- downstream compilations-trimId omit_prags id- | omit_prags, not (isImplicitId id)+trimId do_trim id+ | do_trim, not (isImplicitId id) = id `setIdInfo` vanillaIdInfo `setIdUnfolding` idUnfolding id -- We respect the final unfolding chosen by tidyTopIdInfo.@@ -673,21 +644,20 @@ -- -- Bool => expose unfolding or not. -chooseExternalIds :: HscEnv+chooseExternalIds :: TidyOpts -> Module- -> Bool -> Bool -> [CoreBind] -> [CoreBind] -> [CoreRule] -> IO (UnfoldEnv, TidyOccEnv) -- Step 1 from the notes above -chooseExternalIds hsc_env mod omit_prags expose_all binds implicit_binds imp_id_rules+chooseExternalIds opts mod binds implicit_binds imp_id_rules = do { (unfold_env1,occ_env1) <- search init_work_list emptyVarEnv init_occ_env ; let internal_ids = filter (not . (`elemVarEnv` unfold_env1)) binders ; tidy_internal internal_ids unfold_env1 occ_env1 } where- name_cache = hsc_NC hsc_env+ name_cache = opt_name_cache opts -- init_ext_ids is the initial list of Ids that should be -- externalised. It serves as the starting point for finding a@@ -701,18 +671,14 @@ init_ext_ids = sortBy (compare `on` getOccName) $ filter is_external binders -- An Id should be external if either (a) it is exported,- -- (b) it appears in the RHS of a local rule for an imported Id, or- -- See Note [Which rules to expose]- is_external id = isExportedId id || id `elemVarSet` rule_rhs_vars+ -- (b) local rules are exposed and it appears in the RHS of a local rule for+ -- an imported Id, or See Note [Which rules to expose]+ is_external id+ | isExportedId id = True+ | opt_expose_rules opts = id `elemVarSet` rule_rhs_vars+ | otherwise = False - rule_rhs_vars- -- No rules are exposed when omit_prags is enabled see #19836- -- imp_id_rules are the RULES in /this/ module for /imported/ Ids- -- If omit_prags is True, these rules won't be put in the interface file.- -- But if omit_prags is False, so imp_id_rules are in the interface file for- -- this module, then the local-defined Ids they use must be made external.- | omit_prags = emptyVarSet- | otherwise = mapUnionVarSet ruleRhsFreeVars imp_id_rules+ rule_rhs_vars = mapUnionVarSet ruleRhsFreeVars imp_id_rules binders = map fst $ flattenBinds binds implicit_binders = bindersOfBinds implicit_binds@@ -758,7 +724,7 @@ | otherwise = do (occ_env', name') <- tidyTopName mod name_cache (Just referrer) occ_env idocc let- (new_ids, show_unfold) = addExternal omit_prags expose_all refined_id+ (new_ids, show_unfold) = addExternal opts refined_id -- 'idocc' is an *occurrence*, but we need to see the -- unfolding in the *definition*; so look up in binder_set@@ -780,9 +746,9 @@ let unfold_env' = extendVarEnv unfold_env id (name',False) tidy_internal ids unfold_env' occ_env' -addExternal :: Bool -> Bool -> Id -> ([Id], Bool)-addExternal omit_prags expose_all id- | omit_prags+addExternal :: TidyOpts -> Id -> ([Id], Bool)+addExternal opts id+ | ExposeNone <- opt_expose_unfoldings opts , not (isCompulsoryUnfolding unfolding) = ([], False) -- See Note [Always expose compulsory unfoldings] -- in GHC.HsToCore@@ -804,8 +770,9 @@ -- In GHCi the unfolding is used by importers show_unfolding (CoreUnfolding { uf_src = src, uf_guidance = guidance })- = expose_all -- 'expose_all' says to expose all- -- unfoldings willy-nilly+ = opt_expose_unfoldings opts == ExposeAll+ -- 'ExposeAll' says to expose all+ -- unfoldings willy-nilly || isStableSource src -- Always expose things whose -- source is an inline rule@@ -1000,13 +967,13 @@ This stuff is the only reason for the ru_auto field in a Rule. -} -findExternalRules :: Bool -- Omit pragmas+findExternalRules :: TidyOpts -> [CoreBind] -> [CoreRule] -- Local rules for imported fns -> UnfoldEnv -- Ids that are exported, so we need their rules -> ([CoreBind], [CoreRule]) -- See Note [Finding external rules]-findExternalRules omit_prags binds imp_id_rules unfold_env+findExternalRules opts binds imp_id_rules unfold_env = (trimmed_binds, filter keep_rule all_rules) where imp_rules = filter expose_rule imp_id_rules@@ -1031,7 +998,7 @@ -- been discarded; see Note [Trimming auto-rules] expose_rule rule- | omit_prags = False+ | not (opt_expose_rules opts) = False | otherwise = all is_external_id (ruleLhsFreeIdsList rule) -- Don't expose a rule whose LHS mentions a locally-defined -- Id that is completely internal (i.e. not visible to an
compiler/GHC/Iface/Tidy/StaticPtrTable.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE ViewPatterns #-} -- | Code generation for the Static Pointer Table --@@ -48,9 +48,11 @@ -- module GHC.Iface.Tidy.StaticPtrTable- ( sptCreateStaticBinds- , sptModuleInitCode- ) where+ ( sptCreateStaticBinds+ , sptModuleInitCode+ , StaticPtrOpts (..)+ )+where {- Note [Grand plan for static forms] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -126,37 +128,35 @@ import GHC.Prelude import GHC.Platform -import GHC.Driver.Session-import GHC.Driver.Env- import GHC.Core import GHC.Core.Utils (collectMakeStaticArgs) import GHC.Core.DataCon-import GHC.Core.Make (mkStringExprFSWith)+import GHC.Core.Make (mkStringExprFSWith,MkStringIds(..)) import GHC.Core.Type import GHC.Cmm.CLabel import GHC.Unit.Module import GHC.Utils.Outputable as Outputable-import GHC.Utils.Panic-import GHC.Builtin.Names-import GHC.Tc.Utils.Env (lookupGlobal) import GHC.Linker.Types -import GHC.Types.Name import GHC.Types.Id-import GHC.Types.TyThing import GHC.Types.ForeignStubs+import GHC.Data.Maybe -import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.State.Strict import Data.List (intercalate)-import Data.Maybe import GHC.Fingerprint-import qualified GHC.LanguageExtensions as LangExt +data StaticPtrOpts = StaticPtrOpts+ { opt_platform :: !Platform -- ^ Target platform+ , opt_gen_cstub :: !Bool -- ^ Generate CStub or not+ , opt_mk_string :: !MkStringIds -- ^ Ids for `unpackCString[Utf8]#`+ , opt_static_ptr_info_datacon :: !DataCon -- ^ `StaticPtrInfo` datacon+ , opt_static_ptr_datacon :: !DataCon -- ^ `StaticPtr` datacon+ }+ -- | Replaces all bindings of the form -- -- > b = /\ ... -> makeStatic location value@@ -170,16 +170,13 @@ -- -- It also yields the C stub that inserts these bindings into the static -- pointer table.-sptCreateStaticBinds :: HscEnv -> Module -> CoreProgram- -> IO ([SptEntry], CoreProgram)-sptCreateStaticBinds hsc_env this_mod binds- | not (xopt LangExt.StaticPointers dflags) =- return ([], binds)- | otherwise = do- -- Make sure the required interface files are loaded.- _ <- lookupGlobal hsc_env unpackCStringName+sptCreateStaticBinds :: StaticPtrOpts -> Module -> CoreProgram -> IO ([SptEntry], Maybe CStub, CoreProgram)+sptCreateStaticBinds opts this_mod binds = do (fps, binds') <- evalStateT (go [] [] binds) 0- return (fps, binds')+ let cstub+ | opt_gen_cstub opts = Just (sptModuleInitCode (opt_platform opts) this_mod fps)+ | otherwise = Nothing+ return (fps, cstub, binds') where go fps bs xs = case xs of [] -> return (reverse fps, reverse bs)@@ -187,8 +184,6 @@ (fps', bnd') <- replaceStaticBind bnd go (reverse fps' ++ fps) (bnd' : bs) xs' - dflags = hsc_dflags hsc_env- -- Generates keys and replaces 'makeStatic' with 'StaticPtr'. -- -- The 'Int' state is used to produce a different key for each binding.@@ -214,19 +209,16 @@ mkStaticBind t srcLoc e = do i <- get put (i + 1)- staticPtrInfoDataCon <-- lift $ lookupDataConHscEnv staticPtrInfoDataConName+ let staticPtrInfoDataCon = opt_static_ptr_info_datacon opts let fp@(Fingerprint w0 w1) = mkStaticPtrFingerprint i- info <- mkConApp staticPtrInfoDataCon <$>- (++[srcLoc]) <$>- mapM (mkStringExprFSWith (lift . lookupIdHscEnv))- [ unitFS $ moduleUnit this_mod- , moduleNameFS $ moduleName this_mod- ]+ let mk_string_fs = mkStringExprFSWith (opt_mk_string opts)+ let info = mkConApp staticPtrInfoDataCon+ [ mk_string_fs $ unitFS $ moduleUnit this_mod+ , mk_string_fs $ moduleNameFS $ moduleName this_mod+ , srcLoc+ ] - -- The module interface of GHC.StaticPtr should be loaded at least- -- when looking up 'fromStatic' during type-checking.- staticPtrDataCon <- lift $ lookupDataConHscEnv staticPtrDataConName+ let staticPtrDataCon = opt_static_ptr_datacon opts return (fp, mkConApp staticPtrDataCon [ Type t , mkWord64LitWord64 w0@@ -241,17 +233,6 @@ , show n ] - lookupIdHscEnv :: Name -> IO Id- lookupIdHscEnv n = lookupType hsc_env n >>=- maybe (getError n) (return . tyThingId)-- lookupDataConHscEnv :: Name -> IO DataCon- lookupDataConHscEnv n = lookupType hsc_env n >>=- maybe (getError n) (return . tyThingDataCon)-- getError n = pprPanic "sptCreateStaticBinds.get: not found" $- text "Couldn't find" <+> ppr n- -- | @sptModuleInitCode module fps@ is a C stub to insert the static entries -- of @module@ into the static pointer table. --@@ -259,11 +240,12 @@ -- its fingerprint. sptModuleInitCode :: Platform -> Module -> [SptEntry] -> CStub sptModuleInitCode _ _ [] = mempty-sptModuleInitCode platform this_mod entries = CStub $ vcat- [ text "static void hs_spt_init_" <> ppr this_mod- <> text "(void) __attribute__((constructor));"- , text "static void hs_spt_init_" <> ppr this_mod <> text "(void)"- , braces $ vcat $+sptModuleInitCode platform this_mod entries =+ initializerCStub platform init_fn_nm empty init_fn_body `mappend`+ finalizerCStub platform fini_fn_nm empty fini_fn_body+ where+ init_fn_nm = mkInitializerStubLabel this_mod "spt"+ init_fn_body = vcat [ text "static StgWord64 k" <> int i <> text "[2] = " <> pprFingerprint fp <> semi $$ text "extern StgPtr "@@ -277,17 +259,15 @@ <> semi | (i, SptEntry n fp) <- zip [0..] entries ]- , text "static void hs_spt_fini_" <> ppr this_mod- <> text "(void) __attribute__((destructor));"- , text "static void hs_spt_fini_" <> ppr this_mod <> text "(void)"- , braces $ vcat $++ fini_fn_nm = mkFinalizerStubLabel this_mod "spt"+ fini_fn_body = vcat [ text "StgWord64 k" <> int i <> text "[2] = " <> pprFingerprint fp <> semi $$ text "hs_spt_remove" <> parens (char 'k' <> int i) <> semi | (i, (SptEntry _ fp)) <- zip [0..] entries ]- ]- where+ pprFingerprint :: Fingerprint -> SDoc pprFingerprint (Fingerprint w1 w2) = braces $ hcat $ punctuate comma
compiler/GHC/IfaceToCore.hs view
@@ -38,6 +38,7 @@ import GHC.Iface.Env import GHC.StgToCmm.Types+import GHC.Runtime.Heap.Layout import GHC.Tc.Errors.Types import GHC.Tc.TyCl.Build@@ -602,7 +603,7 @@ return $ SelfBoot { sb_mds = mds , sb_tcs = mkNameSet tcs } where- -- | Retuerns @True@ if, when you call 'tcIfaceDecl' on+ -- Retuerns @True@ if, when you call 'tcIfaceDecl' on -- this 'IfaceDecl', an ATyCon would be returned. -- NB: This code assumes that a TyCon cannot be implicit. isIfaceTyCon IfaceId{} = False
compiler/GHC/Linker/Loader.hs view
@@ -69,9 +69,6 @@ import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Utils.Panic.Plain-#if defined(CAN_LOAD_DLL)-import GHC.Utils.Constants (isWindowsHost, isDarwinHost)-#endif import GHC.Utils.Error import GHC.Utils.Logger import GHC.Utils.TmpFs@@ -1295,23 +1292,6 @@ -- letting go of them (plus of course depopulating -- the symbol table which is done in the main body) --- If this package is already part of the GHCi binary, we'll already--- have the right DLLs for this package loaded, so don't try to--- load them again.------ But on Win32 we must load them 'again'; doing so is a harmless no-op--- as far as the loader is concerned, but it does initialise the list--- of DLL handles that rts/Linker.c maintains, and that in turn is--- used by lookupSymbol. So we must call addDLL for each library--- just to get the DLL handle into the list.-#if defined(CAN_LOAD_DLL)-partOfGHCi :: [PackageName]-partOfGHCi- | isWindowsHost || isDarwinHost = []- | otherwise = map (PackageName . mkFastString)- ["base", "template-haskell", "editline"]-#endif- showLS :: LibrarySpec -> String showLS (Objects nms) = "(static) [" ++ intercalate ", " nms ++ "]" showLS (Archive nm) = "(static archive) " ++ nm@@ -1429,16 +1409,14 @@ maybePutSDoc logger (text "Loading unit " <> pprUnitInfoForUser pkg <> text " ... ") - -- See comments with partOfGHCi #if defined(CAN_LOAD_DLL)- when (unitPackageName pkg `notElem` partOfGHCi) $ do- loadFrameworks interp platform pkg- -- See Note [Crash early load_dyn and locateLib]- -- Crash early if can't load any of `known_dlls`- mapM_ (load_dyn interp hsc_env True) known_dlls- -- For remaining `dlls` crash early only when there is surely- -- no package's DLL around ... (not is_dyn)- mapM_ (load_dyn interp hsc_env (not is_dyn) . platformSOName platform) dlls+ loadFrameworks interp platform pkg+ -- See Note [Crash early load_dyn and locateLib]+ -- Crash early if can't load any of `known_dlls`+ mapM_ (load_dyn interp hsc_env True) known_dlls+ -- For remaining `dlls` crash early only when there is surely+ -- no package's DLL around ... (not is_dyn)+ mapM_ (load_dyn interp hsc_env (not is_dyn) . platformSOName platform) dlls #endif -- After loading all the DLLs, we can load the static objects. -- Ordering isn't important here, because we do one final link
compiler/GHC/Llvm/Ppr.hs view
@@ -569,6 +569,7 @@ LMStaticStr s t -> ppr t <> text " c\"" <> ftext s <> text "\\00\"" LMStaticArray d t -> ppr t <> text " [" <> ppCommaJoin (map (ppStatic opts) d) <> char ']' LMStaticStruc d t -> ppr t <> text "<{" <> ppCommaJoin (map (ppStatic opts) d) <> text "}>"+ LMStaticStrucU d t -> ppr t <> text "{" <> ppCommaJoin (map (ppStatic opts) d) <> text "}" LMStaticPointer v -> ppVar opts v LMTrunc v t -> ppr t <> text " trunc (" <> ppStatic opts v <> text " to " <> ppr t <> char ')' LMBitc v t -> ppr t <> text " bitcast (" <> ppStatic opts v <> text " to " <> ppr t <> char ')'
compiler/GHC/Llvm/Types.hs view
@@ -140,6 +140,7 @@ | LMStaticStr LMString LlvmType -- ^ Defines a static 'LMString' | LMStaticArray [LlvmStatic] LlvmType -- ^ A static array | LMStaticStruc [LlvmStatic] LlvmType -- ^ A static structure type+ | LMStaticStrucU [LlvmStatic] LlvmType -- ^ A static structure type | LMStaticPointer LlvmVar -- ^ A pointer to other data -- static expressions, could split out but leave@@ -191,6 +192,7 @@ getStatType (LMStaticStr _ t) = t getStatType (LMStaticArray _ t) = t getStatType (LMStaticStruc _ t) = t+getStatType (LMStaticStrucU _ t) = t getStatType (LMStaticPointer v) = getVarType v getStatType (LMTrunc _ t) = t getStatType (LMBitc _ t) = t
compiler/GHC/Plugins.hs view
@@ -58,6 +58,9 @@ , module GHC.Unit.Module.ModIface , module GHC.Types.Meta , module GHC.Types.SourceError+ , module GHC.Parser.Errors.Types+ , module GHC.Types.Error+ , module GHC.Hs , -- * Getting 'Name's thNameToGhcName )@@ -139,6 +142,11 @@ import GHC.Tc.Utils.Env ( lookupGlobal ) import GHC.Tc.Errors.Hole.FitTypes++-- For parse result plugins+import GHC.Parser.Errors.Types ( PsWarning, PsError )+import GHC.Types.Error ( Messages )+import GHC.Hs ( HsParsedModule ) import qualified Language.Haskell.TH as TH
+ compiler/GHC/Rename/Doc.hs view
@@ -0,0 +1,46 @@+module GHC.Rename.Doc ( rnHsDoc, rnLHsDoc, rnLDocDecl, rnDocDecl ) where++import GHC.Prelude++import GHC.Tc.Types+import GHC.Hs+import GHC.Types.Name.Reader+import GHC.Types.Name+import GHC.Types.SrcLoc+import GHC.Tc.Utils.Monad (getGblEnv)+import GHC.Types.Avail+import GHC.Rename.Env++rnLHsDoc :: LHsDoc GhcPs -> RnM (LHsDoc GhcRn)+rnLHsDoc = traverse rnHsDoc++rnLDocDecl :: LDocDecl GhcPs -> RnM (LDocDecl GhcRn)+rnLDocDecl = traverse rnDocDecl++rnDocDecl :: DocDecl GhcPs -> RnM (DocDecl GhcRn)+rnDocDecl (DocCommentNext doc) = do+ doc' <- rnLHsDoc doc+ pure $ (DocCommentNext doc')+rnDocDecl (DocCommentPrev doc) = do+ doc' <- rnLHsDoc doc+ pure $ (DocCommentPrev doc')+rnDocDecl (DocCommentNamed n doc) = do+ doc' <- rnLHsDoc doc+ pure $ (DocCommentNamed n doc')+rnDocDecl (DocGroup i doc) = do+ doc' <- rnLHsDoc doc+ pure $ (DocGroup i doc')++rnHsDoc :: WithHsDocIdentifiers a GhcPs -> RnM (WithHsDocIdentifiers a GhcRn)+rnHsDoc (WithHsDocIdentifiers s ids) = do+ gre <- tcg_rdr_env <$> getGblEnv+ pure (WithHsDocIdentifiers s (rnHsDocIdentifiers gre ids))++rnHsDocIdentifiers :: GlobalRdrEnv+ -> [Located RdrName]+ -> [Located Name]+rnHsDocIdentifiers gre ns = concat+ [ map (L l . greNamePrintableName . gre_name) (lookupGRE_RdrName c gre)+ | L l rdr_name <- ns+ , c <- dataTcOccs rdr_name+ ]
compiler/GHC/Rename/Env.hs view
@@ -1047,8 +1047,25 @@ = do { mb_name <- lookupOccRn_maybe rdr_name ; case mb_name of Just name -> return name- Nothing -> lookup_demoted rdr_name }+ Nothing ->+ if occName rdr_name == occName eqTyCon_RDR -- See Note [eqTyCon (~) compatibility fallback]+ then eqTyConName <$ addDiagnostic TcRnTypeEqualityOutOfScope+ else lookup_demoted rdr_name } +{- Note [eqTyCon (~) compatibility fallback]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Before GHC Proposal #371, the (~) type operator used in type equality+constraints (a~b) was considered built-in syntax.++This had two implications:++1. Users could use it without importing it from Data.Type.Equality or Prelude.+2. TypeOperators were not required to use it (it was guarded behind TypeFamilies/GADTs instead)++To ease migration and minimize breakage, we continue to support those usages+but emit appropriate warnings.+-}+ lookup_demoted :: RdrName -> RnM Name lookup_demoted rdr_name | Just demoted_rdr <- demoteRdrName rdr_name@@ -1566,7 +1583,7 @@ extra | imp_mod == moduleName name_mod = Outputable.empty | otherwise = text ", but defined in" <+> ppr name_mod -lookupImpDeprec :: ModIface -> GlobalRdrElt -> Maybe WarningTxt+lookupImpDeprec :: ModIface -> GlobalRdrElt -> Maybe (WarningTxt GhcRn) lookupImpDeprec iface gre = mi_warn_fn (mi_final_exts iface) (greOccName gre) `mplus` -- Bleat if the thing, case gre_par gre of -- or its parent, is warn'd@@ -1919,13 +1936,7 @@ = [rdr_name] where occ = rdrNameOcc rdr_name- rdr_name_tc =- case rdr_name of- -- The (~) type operator is always in scope, so we need a special case- -- for it here, or else :info (~) fails in GHCi.- -- See Note [eqTyCon (~) is built-in syntax]- Unqual occ | occNameFS occ == fsLit "~" -> eqTyCon_RDR- _ -> setRdrNameSpace rdr_name tcName+ rdr_name_tc = setRdrNameSpace rdr_name tcName {- Note [dataTcOccs and Exact Names]
compiler/GHC/Rename/Expr.hs view
@@ -47,7 +47,7 @@ , genHsVar, genLHsVar, genHsApp, genHsApps , genAppType ) import GHC.Rename.Unbound ( reportUnboundName )-import GHC.Rename.Splice ( rnBracket, rnSpliceExpr, checkThLocalName )+import GHC.Rename.Splice ( rnTypedBracket, rnUntypedBracket, rnSpliceExpr, checkThLocalName ) import GHC.Rename.HsType import GHC.Rename.Pat import GHC.Driver.Session@@ -337,7 +337,8 @@ ------------------------------------------ -- Template Haskell extensions-rnExpr e@(HsBracket _ br_body) = rnBracket e br_body+rnExpr e@(HsTypedBracket _ br_body) = rnTypedBracket e br_body+rnExpr e@(HsUntypedBracket _ br_body) = rnUntypedBracket e br_body rnExpr (HsSpliceE _ splice) = rnSpliceExpr splice @@ -541,7 +542,8 @@ let fvExpr' = filterNameSet (nameIsLocalOrFrom mod) fvExpr return (HsStatic fvExpr' expr', fvExpr) -{- *********************************************************************+{-+************************************************************************ * * Arrow notation * *@@ -556,7 +558,8 @@ rnExpr other = pprPanic "rnExpr: unexpected expression" (ppr other) -- HsWrap -{- *********************************************************************+{-+************************************************************************ * * Operator sections * *
compiler/GHC/Rename/Expr.hs-boot view
@@ -1,6 +1,12 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ConstraintKinds #-} module GHC.Rename.Expr where++#if MIN_VERSION_GLASGOW_HASKELL(9,3,0,0)+import Data.Type.Equality (type (~))+#endif+ import GHC.Types.Name import GHC.Hs import GHC.Types.Name.Set ( FreeVars )
compiler/GHC/Rename/HsType.hs view
@@ -48,6 +48,7 @@ import GHC.Driver.Session import GHC.Hs import GHC.Rename.Env+import GHC.Rename.Doc import GHC.Rename.Utils ( mapFvRn, bindLocalNamesFV , typeAppErr, newLocalBndrRn, checkDupRdrNamesN , checkShadowedRdrNames, warnForallIdentifier )@@ -629,7 +630,7 @@ rnHsTyKi env ty@(HsOpTy _ ty1 l_op ty2) = setSrcSpan (getLocA l_op) $- do { (l_op', fvs1) <- rnHsTyOp env ty l_op+ do { (l_op', fvs1) <- rnHsTyOp env (ppr ty) l_op ; fix <- lookupTyFixityRn l_op' ; (ty1', fvs2) <- rnLHsTyKi env ty1 ; (ty2', fvs3) <- rnLHsTyKi env ty2@@ -733,7 +734,8 @@ rnHsTyKi env (HsDocTy x ty haddock_doc) = do { (ty', fvs) <- rnLHsTyKi env ty- ; return (HsDocTy x ty' haddock_doc, fvs) }+ ; haddock_doc' <- rnLHsDoc haddock_doc+ ; return (HsDocTy x ty' haddock_doc', fvs) } -- See Note [Renaming HsCoreTys] rnHsTyKi env (XHsType ty)@@ -822,16 +824,15 @@ ; return (L loc tyvar) } ---------------rnHsTyOp :: Outputable a- => RnTyKiEnv -> a -> LocatedN RdrName+rnHsTyOp :: RnTyKiEnv -> SDoc -> LocatedN RdrName -> RnM (LocatedN Name, FreeVars) rnHsTyOp env overall_ty (L loc op)- = do { ops_ok <- xoptM LangExt.TypeOperators- ; op' <- rnTyVar env op- ; unless (ops_ok || op' `hasKey` eqTyConKey) $- addErr $ TcRnUnknownMessage $ mkPlainError noHints (opTyErr op overall_ty)- ; let l_op' = L loc op'- ; return (l_op', unitFV op') }+ = do { op' <- rnTyVar env op+ ; unlessXOptM LangExt.TypeOperators $+ if (op' `hasKey` eqTyConKey) -- See [eqTyCon (~) compatibility fallback] in GHC.Rename.Env+ then addDiagnostic TcRnTypeEqualityRequiresOperators+ else addErr $ TcRnIllegalTypeOperator overall_ty op+ ; return (L loc op', unitFV op') } -------------- checkWildCard :: RnTyKiEnv@@ -1272,7 +1273,8 @@ = do { mapM_ (\(L _ (FieldOcc _ rdr_name)) -> warnForallIdentifier rdr_name) names ; let new_names = map (fmap (lookupField fl_env)) names ; (new_ty, fvs) <- rnLHsTyKi env ty- ; return (L l (ConDeclField noAnn new_names new_ty haddock_doc)+ ; haddock_doc' <- traverse rnLHsDoc haddock_doc+ ; return (L l (ConDeclField noAnn new_names new_ty haddock_doc') , fvs) } lookupField :: FastStringEnv FieldLabel -> FieldOcc GhcPs -> FieldOcc GhcRn@@ -1659,11 +1661,6 @@ vcat [ text "Unused quantified type variable" <+> quotes (ppr tv) , inHsDocContext doc ] addDiagnosticAt (locA loc) msg--opTyErr :: Outputable a => RdrName -> a -> SDoc-opTyErr op overall_ty- = hang (text "Illegal operator" <+> quotes (ppr op) <+> text "in type" <+> quotes (ppr overall_ty))- 2 (text "Use TypeOperators to allow operators in types") {- ************************************************************************
compiler/GHC/Rename/Module.hs view
@@ -13,7 +13,7 @@ -} module GHC.Rename.Module (- rnSrcDecls, addTcgDUs, findSplice+ rnSrcDecls, addTcgDUs, findSplice, rnWarningTxt ) where import GHC.Prelude@@ -27,6 +27,7 @@ import GHC.Types.Name.Reader import GHC.Rename.HsType import GHC.Rename.Bind+import GHC.Rename.Doc import GHC.Rename.Env import GHC.Rename.Utils ( mapFvRn, bindLocalNames , checkDupRdrNamesN, bindLocalNamesFV@@ -37,7 +38,7 @@ import GHC.Rename.Unbound ( mkUnboundName, notInScopeErr, WhereLooking(WL_Global) ) import GHC.Rename.Names import GHC.Tc.Errors.Types-import GHC.Tc.Errors.Ppr (withHsDocContext)+import GHC.Tc.Errors.Ppr (withHsDocContext, pprScopeError ) import GHC.Tc.Gen.Annotation ( annCtxt ) import GHC.Tc.Utils.Monad @@ -68,7 +69,6 @@ import GHC.Types.Unique.Set import GHC.Data.OrdList import qualified GHC.LanguageExtensions as LangExt-import GHC.Tc.Errors.Ppr (pprScopeError) import Control.Monad import Control.Arrow ( first )@@ -206,6 +206,7 @@ (rn_default_decls, src_fvs5) <- rnList rnDefaultDecl default_decls ; (rn_deriv_decls, src_fvs6) <- rnList rnSrcDerivDecl deriv_decls ; (rn_splice_decls, src_fvs7) <- rnList rnSpliceDecl splice_decls ;+ rn_docs <- traverse rnLDocDecl docs ; last_tcg_env <- getGblEnv ; -- (I) Compute the results and return@@ -221,7 +222,7 @@ hs_annds = rn_ann_decls, hs_defds = rn_default_decls, hs_ruleds = rn_rule_decls,- hs_docs = docs } ;+ hs_docs = rn_docs } ; tcf_bndrs = hsTyClForeignBinders rn_tycl_decls rn_foreign_decls ; other_def = (Just (mkNameSet tcf_bndrs), emptyNameSet) ;@@ -265,7 +266,7 @@ -} -- checks that the deprecations are defined locally, and that there are no duplicates-rnSrcWarnDecls :: NameSet -> [LWarnDecls GhcPs] -> RnM Warnings+rnSrcWarnDecls :: NameSet -> [LWarnDecls GhcPs] -> RnM (Warnings GhcRn) rnSrcWarnDecls _ [] = return NoWarnings @@ -285,13 +286,23 @@ -- ensures that the names are defined locally = do { names <- concatMapM (lookupLocalTcNames sig_ctxt what . unLoc) rdr_names- ; return [(rdrNameOcc rdr, txt) | (rdr, _) <- names] }+ ; txt' <- rnWarningTxt txt+ ; return [(rdrNameOcc rdr, txt') | (rdr, _) <- names] } what = text "deprecation" warn_rdr_dups = findDupRdrNames $ concatMap (\(L _ (Warning _ ns _)) -> ns) decls +rnWarningTxt :: WarningTxt GhcPs -> RnM (WarningTxt GhcRn)+rnWarningTxt (WarningTxt st wst) = do+ wst' <- traverse (traverse rnHsDoc) wst+ pure (WarningTxt st wst')+rnWarningTxt (DeprecatedTxt st wst) = do+ wst' <- traverse (traverse rnHsDoc) wst+ pure (DeprecatedTxt st wst')++ findDupRdrNames :: [LocatedN RdrName] -> [NonEmpty (LocatedN RdrName)] findDupRdrNames = findDupsEq (\ x -> \ y -> rdrNameOcc (unLoc x) == rdrNameOcc (unLoc y)) @@ -444,7 +455,7 @@ "https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/semigroup-monoid" where- -- | Warn about unsound/non-canonical 'Applicative'/'Monad' instance+ -- Warn about unsound/non-canonical 'Applicative'/'Monad' instance -- declarations. Specifically, the following conditions are verified: -- -- In 'Monad' instances declarations:@@ -490,7 +501,7 @@ | otherwise = return () - -- | Check whether Monoid(mappend) is defined in terms of+ -- Check whether Monoid(mappend) is defined in terms of -- Semigroup((<>)) (and not the other way round). Specifically, -- the following conditions are verified: --@@ -529,7 +540,7 @@ | otherwise = return () - -- | test whether MatchGroup represents a trivial \"lhsName = rhsName\"+ -- test whether MatchGroup represents a trivial \"lhsName = rhsName\" -- binding, and return @Just rhsName@ if this is the case isAliasMG :: MatchGroup GhcRn (LHsExpr GhcRn) -> Maybe Name isAliasMG MG {mg_alts = (L _ [L _ (Match { m_pats = []@@ -1879,11 +1890,12 @@ -- and the methods are already in scope ; let all_fvs = meth_fvs `plusFV` stuff_fvs `plusFV` fv_at_defs+ ; docs' <- traverse rnLDocDecl docs ; return (ClassDecl { tcdCtxt = context', tcdLName = lcls', tcdTyVars = tyvars', tcdFixity = fixity, tcdFDs = fds', tcdSigs = sigs', tcdMeths = mbinds', tcdATs = ats', tcdATDefs = at_defs',- tcdDocs = docs, tcdCExt = all_fvs },+ tcdDocs = docs', tcdCExt = all_fvs }, all_fvs ) } where cls_doc = ClassDeclCtx lcls@@ -2329,10 +2341,11 @@ [ text "ex_tvs:" <+> ppr ex_tvs , text "new_ex_dqtvs':" <+> ppr new_ex_tvs ]) + ; mb_doc' <- traverse rnLHsDoc mb_doc ; return (decl { con_ext = noAnn , con_name = new_name, con_ex_tvs = new_ex_tvs , con_mb_cxt = new_context, con_args = new_args- , con_doc = mb_doc+ , con_doc = mb_doc' , con_forall = forall_ }, -- Remove when #18311 is fixed all_fvs) }} @@ -2373,10 +2386,11 @@ ; traceRn "rnConDecl (ConDeclGADT)" (ppr names $$ ppr outer_bndrs')+ ; new_mb_doc <- traverse rnLHsDoc mb_doc ; return (ConDeclGADT { con_g_ext = noAnn, con_names = new_names , con_bndrs = L l outer_bndrs', con_mb_cxt = new_cxt , con_g_args = new_args, con_res_ty = new_res_ty- , con_doc = mb_doc },+ , con_doc = new_mb_doc }, all_fvs) } } rnMbContext :: HsDocContext -> Maybe (LHsContext GhcPs)
compiler/GHC/Rename/Names.hs view
@@ -2163,14 +2163,14 @@ missingImportListWarn mod = text "The module" <+> quotes (ppr mod) <+> text "does not have an explicit import list" -moduleWarn :: ModuleName -> WarningTxt -> SDoc+moduleWarn :: ModuleName -> WarningTxt GhcRn -> SDoc moduleWarn mod (WarningTxt _ txt) = sep [ text "Module" <+> quotes (ppr mod) <> colon,- nest 2 (vcat (map (ppr . sl_fs . unLoc) txt)) ]+ nest 2 (vcat (map (ppr . hsDocString . unLoc) txt)) ] moduleWarn mod (DeprecatedTxt _ txt) = sep [ text "Module" <+> quotes (ppr mod) <+> text "is deprecated:",- nest 2 (vcat (map (ppr . sl_fs . unLoc) txt)) ]+ nest 2 (vcat (map (ppr . hsDocString . unLoc) txt)) ] packageImportErr :: TcRnMessage packageImportErr
compiler/GHC/Rename/Splice.hs view
@@ -6,7 +6,7 @@ module GHC.Rename.Splice ( rnTopSpliceDecls, rnSpliceType, rnSpliceExpr, rnSplicePat, rnSpliceDecl,- rnBracket,+ rnTypedBracket, rnUntypedBracket, checkThLocalName , traceSplice, SpliceInfo(..) ) where@@ -73,27 +73,30 @@ ************************************************************************ -} -rnBracket :: HsExpr GhcPs -> HsBracket GhcPs -> RnM (HsExpr GhcRn, FreeVars)-rnBracket e br_body- = addErrCtxt (quotationCtxtDoc br_body) $- do { -- Check that -XTemplateHaskellQuotes is enabled and available- thQuotesEnabled <- xoptM LangExt.TemplateHaskellQuotes+-- Check that -XTemplateHaskellQuotes is enabled and available+checkForTemplateHaskellQuotes :: HsExpr GhcPs -> RnM ()+checkForTemplateHaskellQuotes e =+ do { thQuotesEnabled <- xoptM LangExt.TemplateHaskellQuotes ; unless thQuotesEnabled $ failWith ( TcRnUnknownMessage $ mkPlainError noHints $ vcat [ text "Syntax error on" <+> ppr e , text ("Perhaps you intended to use TemplateHaskell" ++ " or TemplateHaskellQuotes") ] )+ } +rnTypedBracket :: HsExpr GhcPs -> LHsExpr GhcPs -> RnM (HsExpr GhcRn, FreeVars)+rnTypedBracket e br_body+ = addErrCtxt (typedQuotationCtxtDoc br_body) $+ do { checkForTemplateHaskellQuotes e+ -- Check for nested brackets ; cur_stage <- getStage ; case cur_stage of- { Splice Typed -> checkTc (isTypedBracket br_body)- illegalUntypedBracket- ; Splice Untyped -> checkTc (not (isTypedBracket br_body))- illegalTypedBracket+ { Splice Typed -> return ()+ ; Splice Untyped -> failWithTc illegalTypedBracket ; RunSplice _ -> -- See Note [RunSplice ThLevel] in GHC.Tc.Types.- pprPanic "rnBracket: Renaming bracket when running a splice"+ pprPanic "rnTypedBracket: Renaming typed bracket when running a splice" (ppr e) ; Comp -> return () ; Brack {} -> failWithTc illegalBracket@@ -102,26 +105,48 @@ -- Brackets are desugared to code that mentions the TH package ; recordThUse - ; case isTypedBracket br_body of- True -> do { traceRn "Renaming typed TH bracket" empty- ; (body', fvs_e) <-- setStage (Brack cur_stage RnPendingTyped) $- rn_bracket cur_stage br_body- ; return (HsBracket noAnn body', fvs_e) }+ ; traceRn "Renaming typed TH bracket" empty+ ; (body', fvs_e) <- setStage (Brack cur_stage RnPendingTyped) $ rnLExpr br_body - False -> do { traceRn "Renaming untyped TH bracket" empty- ; ps_var <- newMutVar []- ; (body', fvs_e) <-- -- See Note [Rebindable syntax and Template Haskell]- unsetXOptM LangExt.RebindableSyntax $- setStage (Brack cur_stage (RnPendingUntyped ps_var)) $- rn_bracket cur_stage br_body- ; pendings <- readMutVar ps_var- ; return (HsRnBracketOut noExtField body' pendings, fvs_e) }+ ; return (HsTypedBracket noExtField body', fvs_e)+ } -rn_bracket :: ThStage -> HsBracket GhcPs -> RnM (HsBracket GhcRn, FreeVars)-rn_bracket outer_stage br@(VarBr x flg rdr_name)+rnUntypedBracket :: HsExpr GhcPs -> HsQuote GhcPs -> RnM (HsExpr GhcRn, FreeVars)+rnUntypedBracket e br_body+ = addErrCtxt (untypedQuotationCtxtDoc br_body) $+ do { checkForTemplateHaskellQuotes e++ -- Check for nested brackets+ ; cur_stage <- getStage+ ; case cur_stage of+ { Splice Typed -> failWithTc illegalUntypedBracket+ ; Splice Untyped -> return ()+ ; RunSplice _ ->+ -- See Note [RunSplice ThLevel] in GHC.Tc.Types.+ pprPanic "rnUntypedBracket: Renaming untyped bracket when running a splice"+ (ppr e)+ ; Comp -> return ()+ ; Brack {} -> failWithTc illegalBracket+ }++ -- Brackets are desugared to code that mentions the TH package+ ; recordThUse++ ; traceRn "Renaming untyped TH bracket" empty+ ; ps_var <- newMutVar []+ ; (body', fvs_e) <-+ -- See Note [Rebindable syntax and Template Haskell]+ unsetXOptM LangExt.RebindableSyntax $+ setStage (Brack cur_stage (RnPendingUntyped ps_var)) $+ rn_utbracket cur_stage br_body+ ; pendings <- readMutVar ps_var+ ; return (HsUntypedBracket pendings body', fvs_e)++ }++rn_utbracket :: ThStage -> HsQuote GhcPs -> RnM (HsQuote GhcRn, FreeVars)+rn_utbracket outer_stage br@(VarBr x flg rdr_name) = do { name <- lookupOccRn (unLoc rdr_name) ; check_namespace flg name ; this_mod <- getModule@@ -137,7 +162,7 @@ | isTopLevel top_lvl -> when (isExternalName name) (keepAlive name) | otherwise- -> do { traceRn "rn_bracket VarBr"+ -> do { traceRn "rn_utbracket VarBr" (ppr name <+> ppr bind_lvl <+> ppr outer_stage) ; checkTc (thLevel outer_stage + 1 == bind_lvl)@@ -146,16 +171,16 @@ } ; return (VarBr x flg (noLocA name), unitFV name) } -rn_bracket _ (ExpBr x e) = do { (e', fvs) <- rnLExpr e- ; return (ExpBr x e', fvs) }+rn_utbracket _ (ExpBr x e) = do { (e', fvs) <- rnLExpr e+ ; return (ExpBr x e', fvs) } -rn_bracket _ (PatBr x p)+rn_utbracket _ (PatBr x p) = rnPat ThPatQuote p $ \ p' -> return (PatBr x p', emptyFVs) -rn_bracket _ (TypBr x t) = do { (t', fvs) <- rnLHsType TypBrCtx t- ; return (TypBr x t', fvs) }+rn_utbracket _ (TypBr x t) = do { (t', fvs) <- rnLHsType TypBrCtx t+ ; return (TypBr x t', fvs) } -rn_bracket _ (DecBrL x decls)+rn_utbracket _ (DecBrL x decls) = do { group <- groupDecls decls ; gbl_env <- getGblEnv ; let new_gbl_env = gbl_env { tcg_dus = emptyDUs }@@ -165,7 +190,7 @@ rnSrcDecls group -- Discard the tcg_env; it contains only extra info about fixity- ; traceRn "rn_bracket dec" (ppr (tcg_dus tcg_env) $$+ ; traceRn "rn_utbracket dec" (ppr (tcg_dus tcg_env) $$ ppr (duUses (tcg_dus tcg_env))) ; return (DecBrG x group', duUses (tcg_dus tcg_env)) } where@@ -181,10 +206,8 @@ } }} -rn_bracket _ (DecBrG {}) = panic "rn_bracket: unexpected DecBrG"+rn_utbracket _ (DecBrG {}) = panic "rn_ut_bracket: unexpected DecBrG" -rn_bracket _ (TExpBr x e) = do { (e', fvs) <- rnLExpr e- ; return (TExpBr x e', fvs) } -- | Ensure that we are not using a term-level name in a type-level namespace -- or vice-versa. Throws a 'TcRnIncorrectNameSpace' error if there is a problem.@@ -195,8 +218,13 @@ where ns = nameNameSpace nm -quotationCtxtDoc :: HsBracket GhcPs -> SDoc-quotationCtxtDoc br_body+typedQuotationCtxtDoc :: LHsExpr GhcPs -> SDoc+typedQuotationCtxtDoc br_body+ = hang (text "In the Template Haskell typed quotation")+ 2 (thTyBrackets . ppr $ br_body)++untypedQuotationCtxtDoc :: HsQuote GhcPs -> SDoc+untypedQuotationCtxtDoc br_body = hang (text "In the Template Haskell quotation") 2 (ppr br_body) @@ -213,7 +241,7 @@ illegalUntypedBracket = TcRnUnknownMessage $ mkPlainError noHints $ text "Untyped brackets may only appear in untyped splices." -quotedNameStageErr :: HsBracket GhcPs -> TcRnMessage+quotedNameStageErr :: HsQuote GhcPs -> TcRnMessage quotedNameStageErr br = TcRnUnknownMessage $ mkPlainError noHints $ sep [ text "Stage error: the non-top-level quoted name" <+> ppr br
compiler/GHC/Runtime/Eval.hs view
@@ -108,6 +108,7 @@ import GHC.Types.Unique.DSet import GHC.Types.TyThing import GHC.Types.BreakInfo+import GHC.Types.Unique.Map import GHC.Unit import GHC.Unit.Module.Graph@@ -121,7 +122,6 @@ import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import Data.List (find,intercalate)-import qualified Data.Map as Map import Control.Monad import Control.Monad.Catch as MC import Data.Array@@ -909,7 +909,7 @@ getDocs :: GhcMonad m => Name- -> m (Either GetDocsFailure (Maybe HsDocString, IntMap HsDocString))+ -> m (Either GetDocsFailure (Maybe [HsDoc GhcRn], IntMap (HsDoc GhcRn))) -- TODO: What about docs for constructors etc.? getDocs name = withSession $ \hsc_env -> do@@ -919,14 +919,14 @@ if isInteractiveModule mod then pure (Left InteractiveName) else do- ModIface { mi_doc_hdr = mb_doc_hdr- , mi_decl_docs = DeclDocMap dmap- , mi_arg_docs = ArgDocMap amap- } <- liftIO $ hscGetModuleInterface hsc_env mod- if isNothing mb_doc_hdr && Map.null dmap && Map.null amap- then pure (Left (NoDocsInIface mod compiled))- else pure (Right ( Map.lookup name dmap- , Map.findWithDefault mempty name amap))+ iface <- liftIO $ hscGetModuleInterface hsc_env mod+ case mi_docs iface of+ Nothing -> pure (Left (NoDocsInIface mod compiled))+ Just Docs { docs_decls = decls+ , docs_args = args+ } ->+ pure (Right ( lookupUniqMap decls name+ , fromMaybe mempty $ lookupUniqMap args name)) where compiled = -- TODO: Find a more direct indicator.@@ -935,16 +935,12 @@ UnhelpfulLoc {} -> True -- | Failure modes for 'getDocs'.---- TODO: Find a way to differentiate between modules loaded without '-haddock'--- and modules that contain no docs. data GetDocsFailure -- | 'nameModule_maybe' returned 'Nothing'. = NameHasNoModule Name - -- | This is probably because the module was loaded without @-haddock@,- -- but it's also possible that the entire module contains no documentation.+ -- | The module was loaded without @-haddock@, | NoDocsInIface Module Bool -- ^ 'True': The module was compiled.@@ -958,11 +954,6 @@ quotes (ppr name) <+> text "has no module where we could look for docs." ppr (NoDocsInIface mod compiled) = vcat [ text "Can't find any documentation for" <+> ppr mod <> char '.'- , text "This is probably because the module was"- <+> text (if compiled then "compiled" else "loaded")- <+> text "without '-haddock',"- , text "but it's also possible that the module contains no documentation."- , text "" , if compiled then text "Try re-compiling with '-haddock'." else text "Try running ':set -haddock' and :load the file again."
compiler/GHC/Stg/BcPrep.hs view
@@ -96,7 +96,7 @@ bcPrepExpr app@StgOpApp{} = pure app bcPrepAlt :: StgAlt -> BcPrepM StgAlt-bcPrepAlt (ac, bndrs, expr) = (,,) ac bndrs <$> bcPrepExpr expr+bcPrepAlt (GenStgAlt con bndrs rhs) = GenStgAlt con bndrs <$> bcPrepExpr rhs bcPrepBind :: StgBinding -> BcPrepM StgBinding -- explicitly match all constructors so we get a warning if we miss any@@ -126,8 +126,7 @@ -- Is this Id a not-necessarily-lifted join point? -- See Note [Not-necessarily-lifted join points], step 1 isNNLJoinPoint :: Id -> Bool-isNNLJoinPoint x = isJoinId x &&- Just True /= isLiftedType_maybe (idType x)+isNNLJoinPoint x = isJoinId x && mightBeUnliftedType (idType x) -- Update an Id's type to take a Void# argument. -- Precondition: the Id is a not-necessarily-lifted join point.
compiler/GHC/Stg/CSE.hs view
@@ -374,7 +374,7 @@ -- Case alternatives -- Extend the CSE environment stgCseAlt :: CseEnv -> AltType -> OutId -> InStgAlt -> OutStgAlt-stgCseAlt env ty case_bndr (DataAlt dataCon, args, rhs)+stgCseAlt env ty case_bndr GenStgAlt{alt_con=DataAlt dataCon, alt_bndrs=args, alt_rhs=rhs} = let (env1, args') = substBndrs env args env2 -- To avoid dealing with unboxed sums StgCse runs after unarise and@@ -389,11 +389,11 @@ = env1 -- see Note [Case 2: CSEing case binders] rhs' = stgCseExpr env2 rhs- in (DataAlt dataCon, args', rhs')-stgCseAlt env _ _ (altCon, args, rhs)+ in GenStgAlt (DataAlt dataCon) args' rhs'+stgCseAlt env _ _ g@GenStgAlt{alt_con=_, alt_bndrs=args, alt_rhs=rhs} = let (env1, args') = substBndrs env args rhs' = stgCseExpr env1 rhs- in (altCon, args', rhs')+ in g {alt_bndrs=args', alt_rhs=rhs'} -- Bindings stgCseBind :: CseEnv -> InStgBinding -> (Maybe OutStgBinding, CseEnv)@@ -445,8 +445,8 @@ where -- see Note [All alternatives are the binder]- isBndr (_, _, StgApp f []) = f == bndr- isBndr _ = False+ isBndr GenStgAlt{alt_con=_,alt_bndrs=_,alt_rhs=StgApp f []} = f == bndr+ isBndr _ = False {- Note [Care with loop breakers]
compiler/GHC/Stg/Debug.hs view
@@ -124,7 +124,8 @@ return (StgTick tick e') collectAlt :: StgAlt -> M StgAlt-collectAlt (ac, bs, e) = (ac, bs, ) <$> collectExpr e+collectAlt alt = do e' <- collectExpr $ alt_rhs alt+ return $! alt { alt_rhs = e' } -- | Try to find the best source position surrounding a 'StgExpr'. The -- heuristic strips ticks from the current expression until it finds one which
compiler/GHC/Stg/FVs.hs view
@@ -270,7 +270,8 @@ f (fvs,ids) (StgVarArg v) = varFVs env v (fvs, ids) altFVs :: Env -> StgAlt -> (CgStgAlt, TopFVs, LocalFVs)-altFVs env (con,bndrs,e)+altFVs env GenStgAlt{alt_con=con, alt_bndrs=bndrs, alt_rhs=e} | (e', top_fvs, lcl_fvs) <- exprFVs (addLocals bndrs env) e , let lcl_fvs' = delDVarSetList lcl_fvs bndrs- = ((con,bndrs, e'), top_fvs, lcl_fvs')+ , let newAlt = GenStgAlt{alt_con=con, alt_bndrs=bndrs, alt_rhs=e'}+ = (newAlt, top_fvs, lcl_fvs')
compiler/GHC/Stg/InferTags.hs view
@@ -82,6 +82,8 @@ It will never point to a thunk, nor will it be tagged `000` (meaning "might be a thunk"). NB: Note that the proper tag for some objects is indeed `000`. Currently this is the case for PAPs. +This works analogous to how `StrictWorkerId`s work. See also Note [Strict Worker Ids].+ Why do we care? Because if we have code like: case strictPair of@@ -119,6 +121,8 @@ So we do our best to establish that `x` is already tagged (which it almost always is) to avoid this cost. In my benchmarks I haven't seen any cases where this causes regressions. +Note that there are similar constraints around Note [Strict Worker Ids].+ Note [How untagged pointers can end up in strict fields] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider@@ -182,6 +186,8 @@ it made the code simpler. But besides implementation complexity there isn't any reason why we couldn't be more rigourous in dealing with functions. +NB: It turned out because of #21193 option two wouldn't really have been an option anyway.+ Note [Tag inference debugging] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There is a flag -dtag-inference-checks which inserts various@@ -333,7 +339,7 @@ inferTagExpr in_env (StgCase scrut bndr ty alts) -- Unboxed tuples get their info from the expression we scrutinise if any- | [(DataAlt con, bndrs, rhs)] <- alts+ | [GenStgAlt{alt_con=DataAlt con, alt_bndrs=bndrs, alt_rhs=rhs}] <- alts , isUnboxedTupleDataCon con , Just infos <- scrut_infos bndrs , let bndrs' = zipWithEqual "inferTagExpr" mk_bndr bndrs infos@@ -350,7 +356,9 @@ -- text "bndr:" <> ppr bndr $$ -- text "infos" <> ppr infos $$ -- text "out_bndrs" <> ppr bndrs') $- (info, StgCase scrut' (noSig in_env bndr) ty [(DataAlt con, bndrs', rhs')])+ (info, StgCase scrut' (noSig in_env bndr) ty [GenStgAlt{ alt_con=DataAlt con+ , alt_bndrs=bndrs'+ , alt_rhs=rhs'}]) | null alts -- Empty case, but I might just be paranoid. = -- pprTrace "inferCase2" empty $@@ -362,11 +370,14 @@ case_env = extendSigEnv in_env [bndr'] (infos, alts')- = unzip [ (info, (con, bndrs', rhs'))- | (con, bndrs, rhs) <- alts+ = unzip [ (info, g {alt_bndrs=bndrs', alt_rhs=rhs'})+ | g@GenStgAlt{ alt_con = con+ , alt_bndrs = bndrs+ , alt_rhs = rhs+ } <- alts , let (alt_env,bndrs') = addAltBndrInfo case_env con bndrs (info, rhs') = inferTagExpr alt_env rhs- ]+ ] alt_info = foldr combineAltInfo TagTagged infos in ( alt_info, StgCase scrut' bndr' ty alts') where
compiler/GHC/Stg/InferTags/Rewrite.hs view
@@ -2,18 +2,18 @@ -- Copyright (c) 2019 Andreas Klebinger -- -{-# LANGUAGE CPP #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralisedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-} module GHC.Stg.InferTags.Rewrite (rewriteTopBinds) where@@ -49,7 +49,6 @@ import Control.Monad import GHC.Types.Basic (CbvMark (NotMarkedCbv, MarkedCbv), isMarkedCbv, TopLevelFlag(..), isTopLevel) import GHC.Types.Var.Set- -- import GHC.Utils.Trace -- import GHC.Driver.Ppr @@ -371,10 +370,10 @@ rewriteCase _ = panic "Impossible: nodeCase" rewriteAlt :: InferStgAlt -> RM TgStgAlt-rewriteAlt (altCon, bndrs, rhs) = do+rewriteAlt alt@GenStgAlt{alt_con=_, alt_bndrs=bndrs, alt_rhs=rhs} = withBinders NotTopLevel bndrs $ do !rhs' <- rewriteExpr False rhs- return $! (altCon, map fst bndrs, rhs')+ return $! alt {alt_bndrs = map fst bndrs, alt_rhs = rhs'} rewriteLet :: InferStgExpr -> RM TgStgExpr rewriteLet (StgLet xt bind expr) = do@@ -421,7 +420,7 @@ else f return $! StgApp f' [] rewriteApp _ (StgApp f args)- -- | pprTrace "rewriteAppOther" (ppr f <+> ppr args) False+ -- pprTrace "rewriteAppOther" (ppr f <+> ppr args) False -- = undefined | Just marks <- idCbvMarks_maybe f , relevant_marks <- dropWhileEndLE (not . isMarkedCbv) marks@@ -450,9 +449,9 @@ mkSeq :: Id -> Id -> TgStgExpr -> TgStgExpr mkSeq id bndr !expr = -- pprTrace "mkSeq" (ppr (id,bndr)) $- let altTy = mkStgAltTypeFromStgAlts bndr [(DEFAULT, [], panic "Not used")]- in- StgCase (StgApp id []) bndr altTy [(DEFAULT, [], expr)]+ let altTy = mkStgAltTypeFromStgAlts bndr alt+ alt = [GenStgAlt {alt_con = DEFAULT, alt_bndrs = [], alt_rhs = expr}]+ in StgCase (StgApp id []) bndr altTy alt -- `mkSeqs args vs mkExpr` will force all vs, and construct -- an argument list args' where each v is replaced by it's evaluated
compiler/GHC/Stg/Lift.hs view
@@ -249,5 +249,7 @@ Just bind' -> pure (StgLetNoEscape noExtFieldSilent bind' body') liftAlt :: LlStgAlt -> LiftM OutStgAlt-liftAlt (con, infos, rhs) = withSubstBndrs (map binderInfoBndr infos) $ \bndrs' ->- (,,) con bndrs' <$> liftExpr rhs+liftAlt alt@GenStgAlt{alt_con=_, alt_bndrs=infos, alt_rhs=rhs} =+ withSubstBndrs (map binderInfoBndr infos) $ \bndrs' ->+ do !rhs' <- liftExpr rhs+ return $! alt {alt_bndrs = bndrs', alt_rhs = rhs'}
compiler/GHC/Stg/Lift/Analysis.hs view
@@ -333,8 +333,8 @@ n :* cd = idDemandInfo bndr tagSkeletonAlt :: CgStgAlt -> (Skeleton, IdSet, LlStgAlt)-tagSkeletonAlt (con, bndrs, rhs)- = (alt_skel, arg_occs, (con, map BoringBinder bndrs, rhs'))+tagSkeletonAlt old@GenStgAlt{alt_con=_, alt_bndrs=bndrs, alt_rhs=rhs}+ = (alt_skel, arg_occs, old {alt_bndrs=fmap BoringBinder bndrs, alt_rhs=rhs'}) where (alt_skel, alt_arg_occs, rhs') = tagSkeletonExpr rhs arg_occs = alt_arg_occs `delVarSetList` bndrs
compiler/GHC/Stg/Lint.hs view
@@ -245,15 +245,20 @@ lintAlt :: (OutputablePass a, BinderP a ~ Id)- => (AltCon, [Id], GenStgExpr a) -> LintM ()+ => GenStgAlt a -> LintM () -lintAlt (DEFAULT, _, rhs) =- lintStgExpr rhs+lintAlt GenStgAlt{ alt_con = DEFAULT+ , alt_bndrs = _+ , alt_rhs = rhs} = lintStgExpr rhs -lintAlt (LitAlt _, _, rhs) =- lintStgExpr rhs+lintAlt GenStgAlt{ alt_con = LitAlt _+ , alt_bndrs = _+ , alt_rhs = rhs} = lintStgExpr rhs -lintAlt (DataAlt _, bndrs, rhs) = do+lintAlt GenStgAlt{ alt_con = DataAlt _+ , alt_bndrs = bndrs+ , alt_rhs = rhs} =+ do mapM_ checkPostUnariseBndr bndrs addInScopeVars bndrs (lintStgExpr rhs)
compiler/GHC/Stg/Stats.hs view
@@ -164,5 +164,4 @@ stat_alts alts `combineSE` countOne StgCases where- stat_alts alts- = combineSEs (map statExpr [ e | (_,_,e) <- alts ])+ stat_alts = combineSEs . fmap (statExpr . alt_rhs)
compiler/GHC/Stg/Unarise.hs view
@@ -447,7 +447,9 @@ -> [OutStgArg] -- non-void args -> InId -> AltType -> [InStgAlt] -> UniqSM OutStgExpr -elimCase rho args bndr (MultiValAlt _) [(_, bndrs, rhs)]+elimCase rho args bndr (MultiValAlt _) [GenStgAlt{ alt_con = _+ , alt_bndrs = bndrs+ , alt_rhs = rhs}] = do let rho1 = extendRho rho bndr (MultiVal args) rho2 | isUnboxedTupleBndr bndr@@ -479,47 +481,55 @@ -------------------------------------------------------------------------------- unariseAlts :: UnariseEnv -> AltType -> InId -> [StgAlt] -> UniqSM [StgAlt]-unariseAlts rho (MultiValAlt n) bndr [(DEFAULT, [], e)]+unariseAlts rho (MultiValAlt n) bndr [GenStgAlt{ alt_con = DEFAULT+ , alt_bndrs = []+ , alt_rhs = e}] | isUnboxedTupleBndr bndr = do (rho', ys) <- unariseConArgBinder rho bndr- e' <- unariseExpr rho' e- return [(DataAlt (tupleDataCon Unboxed n), ys, e')]+ !e' <- unariseExpr rho' e+ return [GenStgAlt (DataAlt (tupleDataCon Unboxed n)) ys e'] -unariseAlts rho (MultiValAlt n) bndr [(DataAlt _, ys, e)]+unariseAlts rho (MultiValAlt n) bndr [GenStgAlt{ alt_con = DataAlt _+ , alt_bndrs = ys+ , alt_rhs = e}] | isUnboxedTupleBndr bndr = do (rho', ys1) <- unariseConArgBinders rho ys massert (ys1 `lengthIs` n) let rho'' = extendRho rho' bndr (MultiVal (map StgVarArg ys1))- e' <- unariseExpr rho'' e- return [(DataAlt (tupleDataCon Unboxed n), ys1, e')]+ !e' <- unariseExpr rho'' e+ return [GenStgAlt (DataAlt (tupleDataCon Unboxed n)) ys1 e'] unariseAlts _ (MultiValAlt _) bndr alts | isUnboxedTupleBndr bndr = pprPanic "unariseExpr: strange multi val alts" (pprPanicAlts alts) -- In this case we don't need to scrutinize the tag bit-unariseAlts rho (MultiValAlt _) bndr [(DEFAULT, _, rhs)]+unariseAlts rho (MultiValAlt _) bndr [GenStgAlt{ alt_con = DEFAULT+ , alt_bndrs = []+ , alt_rhs = rhs}] | isUnboxedSumBndr bndr = do (rho_sum_bndrs, sum_bndrs) <- unariseConArgBinder rho bndr rhs' <- unariseExpr rho_sum_bndrs rhs- return [(DataAlt (tupleDataCon Unboxed (length sum_bndrs)), sum_bndrs, rhs')]+ return [GenStgAlt (DataAlt (tupleDataCon Unboxed (length sum_bndrs))) sum_bndrs rhs'] unariseAlts rho (MultiValAlt _) bndr alts | isUnboxedSumBndr bndr = do (rho_sum_bndrs, scrt_bndrs@(tag_bndr : real_bndrs)) <- unariseConArgBinder rho bndr alts' <- unariseSumAlts rho_sum_bndrs (map StgVarArg real_bndrs) alts let inner_case = StgCase (StgApp tag_bndr []) tag_bndr tagAltTy alts'- return [ (DataAlt (tupleDataCon Unboxed (length scrt_bndrs)),- scrt_bndrs,- inner_case) ]+ return [GenStgAlt{ alt_con = DataAlt (tupleDataCon Unboxed (length scrt_bndrs))+ , alt_bndrs = scrt_bndrs+ , alt_rhs = inner_case+ }] unariseAlts rho _ _ alts = mapM (\alt -> unariseAlt rho alt) alts unariseAlt :: UnariseEnv -> StgAlt -> UniqSM StgAlt-unariseAlt rho (con, xs, e)+unariseAlt rho alt@GenStgAlt{alt_con=_,alt_bndrs=xs,alt_rhs=e} = do (rho', xs') <- unariseConArgBinders rho xs- (con, xs',) <$> unariseExpr rho' e+ !e' <- unariseExpr rho' e+ return $! alt {alt_bndrs = xs', alt_rhs = e'} -------------------------------------------------------------------------------- @@ -537,13 +547,16 @@ -> [StgArg] -- sum components _excluding_ the tag bit. -> StgAlt -- original alternative with sum LHS -> UniqSM StgAlt-unariseSumAlt rho _ (DEFAULT, _, e)- = ( DEFAULT, [], ) <$> unariseExpr rho e+unariseSumAlt rho _ GenStgAlt{alt_con=DEFAULT,alt_bndrs=_,alt_rhs=e}+ = GenStgAlt DEFAULT mempty <$> unariseExpr rho e -unariseSumAlt rho args (DataAlt sumCon, bs, e)- = do let rho' = mapSumIdBinders bs args rho- e' <- unariseExpr rho' e- return ( LitAlt (LitNumber LitNumInt (fromIntegral (dataConTag sumCon))), [], e' )+unariseSumAlt rho args GenStgAlt{ alt_con = DataAlt sumCon+ , alt_bndrs = bs+ , alt_rhs = e+ }+ = do let rho' = mapSumIdBinders bs args rho+ lit_case = LitAlt (LitNumber LitNumInt (fromIntegral (dataConTag sumCon)))+ GenStgAlt lit_case mempty <$> unariseExpr rho' e unariseSumAlt _ scrt alt = pprPanic "unariseSumAlt" (ppr scrt $$ pprPanicAlt alt)@@ -840,12 +853,12 @@ -- Since they are exhaustive, we can replace one with DEFAULT, to avoid -- generating a final test. Remember, the DEFAULT comes first if it exists. mkDefaultLitAlt [] = pprPanic "elimUbxSumExpr.mkDefaultAlt" (text "Empty alts")-mkDefaultLitAlt alts@((DEFAULT, _, _) : _) = alts-mkDefaultLitAlt ((LitAlt{}, [], rhs) : alts) = (DEFAULT, [], rhs) : alts+mkDefaultLitAlt alts@(GenStgAlt{alt_con=DEFAULT,alt_bndrs=_,alt_rhs=_} : _) = alts+mkDefaultLitAlt (alt@GenStgAlt{alt_con=LitAlt{}, alt_bndrs=[]} : alts) = alt {alt_con = DEFAULT} : alts mkDefaultLitAlt alts = pprPanic "mkDefaultLitAlt" (text "Not a lit alt:" <+> pprPanicAlts alts) -pprPanicAlts :: (Outputable a, Outputable b, OutputablePass pass) => [(a,b,GenStgExpr pass)] -> SDoc+pprPanicAlts :: OutputablePass pass => [GenStgAlt pass] -> SDoc pprPanicAlts alts = ppr (map pprPanicAlt alts) -pprPanicAlt :: (Outputable a, Outputable b, OutputablePass pass) => (a,b,GenStgExpr pass) -> SDoc-pprPanicAlt (c,b,e) = ppr (c,b,pprStgExpr panicStgPprOpts e)+pprPanicAlt :: OutputablePass pass => GenStgAlt pass -> SDoc+pprPanicAlt GenStgAlt{alt_con=c,alt_bndrs=b,alt_rhs=e} = ppr (c,b,pprStgExpr panicStgPprOpts e)
compiler/GHC/Stg/Utils.hs view
@@ -42,10 +42,13 @@ -- | Extract the default case alternative -- findDefaultStg :: [Alt b] -> ([Alt b], Maybe (Expr b))-findDefaultStg :: [GenStgAlt p] -> ([(AltCon, [BinderP p], GenStgExpr p)],- Maybe (GenStgExpr p))-findDefaultStg ((DEFAULT, args, rhs) : alts) = assert( null args ) (alts, Just rhs)-findDefaultStg alts = (alts, Nothing)+findDefaultStg+ :: [GenStgAlt p]+ -> ([GenStgAlt p], Maybe (GenStgExpr p))+findDefaultStg (GenStgAlt{ alt_con = DEFAULT+ , alt_bndrs = args+ , alt_rhs = rhs} : alts) = assert( null args ) (alts, Just rhs)+findDefaultStg alts = (alts, Nothing) mkStgAltTypeFromStgAlts :: forall p. Id -> [GenStgAlt p] -> AltType mkStgAltTypeFromStgAlts bndr alts@@ -80,7 +83,7 @@ -- grabbing the one from a constructor alternative -- if one exists. look_for_better_tycon- | (((DataAlt con) ,_, _) : _) <- data_alts =+ | (DataAlt con : _) <- alt_con <$> data_alts = AlgAlt (dataConTyCon con) | otherwise = assert(null data_alts)
compiler/GHC/StgToByteCode.hs view
@@ -884,11 +884,11 @@ -- given an alt, return a discr and code for it. codeAlt :: CgStgAlt -> BcM (Discr, BCInstrList)- codeAlt (DEFAULT, _, rhs)+ codeAlt GenStgAlt{alt_con=DEFAULT,alt_bndrs=_,alt_rhs=rhs} = do rhs_code <- schemeE d_alts s p_alts rhs return (NoDiscr, rhs_code) - codeAlt alt@(_, bndrs, rhs)+ codeAlt alt@GenStgAlt{alt_con=_, alt_bndrs=bndrs, alt_rhs=rhs} -- primitive or nullary constructor alt: no need to UNPACK | null real_bndrs = do rhs_code <- schemeE d_alts s p_alts rhs@@ -939,24 +939,25 @@ where real_bndrs = filterOut isTyVar bndrs - my_discr (DEFAULT, _, _) = NoDiscr {-shouldn't really happen-}- my_discr (DataAlt dc, _, _)- | isUnboxedTupleDataCon dc || isUnboxedSumDataCon dc- = NoDiscr- | otherwise- = DiscrP (fromIntegral (dataConTag dc - fIRST_TAG))- my_discr (LitAlt l, _, _)- = case l of LitNumber LitNumInt i -> DiscrI (fromInteger i)- LitNumber LitNumWord w -> DiscrW (fromInteger w)- LitFloat r -> DiscrF (fromRational r)- LitDouble r -> DiscrD (fromRational r)- LitChar i -> DiscrI (ord i)- _ -> pprPanic "schemeE(StgCase).my_discr" (ppr l)+ my_discr alt = case alt_con alt of+ DEFAULT -> NoDiscr {-shouldn't really happen-}+ DataAlt dc+ | isUnboxedTupleDataCon dc || isUnboxedSumDataCon dc+ -> NoDiscr+ | otherwise+ -> DiscrP (fromIntegral (dataConTag dc - fIRST_TAG))+ LitAlt l -> case l of+ LitNumber LitNumInt i -> DiscrI (fromInteger i)+ LitNumber LitNumWord w -> DiscrW (fromInteger w)+ LitFloat r -> DiscrF (fromRational r)+ LitDouble r -> DiscrD (fromRational r)+ LitChar i -> DiscrI (ord i)+ _ -> pprPanic "schemeE(StgCase).my_discr" (ppr l) maybe_ncons | not isAlgCase = Nothing | otherwise- = case [dc | (DataAlt dc, _, _) <- alts] of+ = case [dc | DataAlt dc <- alt_con <$> alts] of [] -> Nothing (dc:_) -> Just (tyConFamilySize (dataConTyCon dc))
compiler/GHC/StgToCmm.hs view
@@ -15,8 +15,6 @@ import GHC.Prelude as Prelude -import GHC.Driver.Backend- import GHC.StgToCmm.Prof (initCostCentres, ldvEnter) import GHC.StgToCmm.Monad import GHC.StgToCmm.Env@@ -183,12 +181,11 @@ -- emit either a CmmString literal or dump the string in a file and emit a -- CmmFileEmbed literal. -- See Note [Embedding large binary blobs] in GHC.CmmToAsm.Ppr- let bin_blob_threshold = stgToCmmBinBlobThresh cfg- isNCG = platformDefaultBackend (stgToCmmPlatform cfg) == NCG- isSmall = fromIntegral (BS.length str) <= bin_blob_threshold- asString = bin_blob_threshold == 0 || isSmall+ let asString = case stgToCmmBinBlobThresh cfg of+ Just bin_blob_threshold -> fromIntegral (BS.length str) <= bin_blob_threshold+ Nothing -> True - (lit,decl) = if not isNCG || asString+ (lit,decl) = if asString then mkByteStringCLit label str else mkFileEmbedLit label $ unsafePerformIO $ do bFile <- newTempName logger tmpfs (stgToCmmTmpDir cfg) TFL_CurrentModule ".dat"
compiler/GHC/StgToCmm/Bind.hs view
@@ -212,7 +212,7 @@ ) cgRhs id (StgRhsCon cc con mn _ts args)- = withNewTickyCounterCon (idName id) con $+ = withNewTickyCounterCon id con mn $ buildDynCon id mn True cc con (assertNonVoidStgArgs args) -- con args are always non-void, -- see Note [Post-unarisation invariants] in GHC.Stg.Unarise@@ -223,14 +223,16 @@ checkFunctionArgTags (text "TagCheck Failed: Rhs of" <> ppr id) id args profile <- getProfile check_tags <- stgToCmmDoTagCheck <$> getStgToCmmConfig- mkRhsClosure profile check_tags id cc (nonVoidIds (dVarSetElems fvs)) upd_flag args body-+ use_std_ap_thunk <- stgToCmmTickyAP <$> getStgToCmmConfig+ mkRhsClosure profile use_std_ap_thunk check_tags id cc (nonVoidIds (dVarSetElems fvs)) upd_flag args body ------------------------------------------------------------------------ -- Non-constructor right hand sides ------------------------------------------------------------------------ -mkRhsClosure :: Profile -> Bool+mkRhsClosure :: Profile+ -> Bool -- Omit AP Thunks to improve profiling+ -> Bool -- Lint tag inference checks -> Id -> CostCentreStack -> [NonVoid Id] -- Free vars -> UpdateFlag@@ -274,7 +276,7 @@ -} ---------- See Note [Selectors] -------------------mkRhsClosure profile _check_tags bndr _cc+mkRhsClosure profile _ _check_tags bndr _cc [NonVoid the_fv] -- Just one free var upd_flag -- Updatable thunk [] -- A thunk@@ -283,7 +285,9 @@ , StgCase (StgApp scrutinee [{-no args-}]) _ -- ignore bndr (AlgAlt _)- [(DataAlt _, params, sel_expr)] <- strip expr+ [GenStgAlt{ alt_con = DataAlt _+ , alt_bndrs = params+ , alt_rhs = sel_expr}] <- strip expr , StgApp selectee [{-no args-}] <- strip sel_expr , the_fv == scrutinee -- Scrutinee is the only free variable @@ -307,7 +311,7 @@ in cgRhsStdThunk bndr lf_info [StgVarArg the_fv] ---------- See Note [Ap thunks] -------------------mkRhsClosure profile check_tags bndr _cc+mkRhsClosure profile use_std_ap check_tags bndr _cc fvs upd_flag [] -- No args; a thunk@@ -316,7 +320,8 @@ -- We are looking for an "ApThunk"; see data con ApThunk in GHC.StgToCmm.Closure -- of form (x1 x2 .... xn), where all the xi are locals (not top-level) -- So the xi will all be free variables- | args `lengthIs` (n_fvs-1) -- This happens only if the fun_id and+ | use_std_ap+ , args `lengthIs` (n_fvs-1) -- This happens only if the fun_id and -- args are all distinct local variables -- The "-1" is for fun_id -- Missed opportunity: (f x x) is not detected@@ -340,7 +345,7 @@ payload = StgVarArg fun_id : args ---------- Default case -------------------mkRhsClosure profile _check_tags bndr cc fvs upd_flag args body+mkRhsClosure profile _use_ap _check_tags bndr cc fvs upd_flag args body = do { let lf_info = mkClosureLFInfo (profilePlatform profile) bndr NotTopLevel fvs upd_flag args ; (id_info, reg) <- rhsIdInfo bndr lf_info ; return (id_info, gen_code lf_info reg) }@@ -404,13 +409,13 @@ } where gen_code reg -- AHA! A STANDARD-FORM THUNK- = withNewTickyCounterStdThunk (lfUpdatable lf_info) (idName bndr) $+ = withNewTickyCounterStdThunk (lfUpdatable lf_info) (bndr) payload $ do { -- LAY OUT THE OBJECT mod_name <- getModuleName- ; cfg <- getStgToCmmConfig- ; let profile = stgToCmmProfile cfg- ; let platform = stgToCmmPlatform cfg+ ; profile <- getProfile+ ; platform <- getPlatform+ ; let header = if isLFThunk lf_info then ThunkHeader else StdHeader (tot_wds, ptr_wds, payload_w_offsets) = mkVirtHeapOffsets profile header@@ -476,7 +481,8 @@ = withNewTickyCounterThunk (isStaticClosure cl_info) (closureUpdReqd cl_info)- (closureName cl_info) $+ (closureName cl_info)+ (map fst fv_details) $ emitClosureProcAndInfoTable top_lvl bndr lf_info info_tbl [] $ \(_, node, _) -> thunkCode cl_info fv_details cc node body where@@ -488,7 +494,7 @@ arity = length args in -- See Note [OneShotInfo overview] in GHC.Types.Basic.- withNewTickyCounterFun (isOneShotBndr arg0) (closureName cl_info)+ withNewTickyCounterFun (isOneShotBndr arg0) (closureName cl_info) (map fst fv_details) nv_args $ do { ; let
compiler/GHC/StgToCmm/Closure.hs view
@@ -65,6 +65,7 @@ cafBlackHoleInfoTable, indStaticInfoTable, staticClosureNeedsLink,+ mkClosureInfoTableLabel ) where import GHC.Prelude@@ -642,7 +643,7 @@ data ClosureInfo = ClosureInfo {- closureName :: !Name, -- The thing bound to this closure+ closureName :: !Id, -- The thing bound to this closure -- we don't really need this field: it's only used in generating -- code for ticky and profiling, and we could pass the information -- around separately, but it doesn't do much harm to keep it here.@@ -679,13 +680,12 @@ -> String -- String descriptor -> ClosureInfo mkClosureInfo profile is_static id lf_info tot_wds ptr_wds val_descr- = ClosureInfo { closureName = name+ = ClosureInfo { closureName = id , closureLFInfo = lf_info , closureInfoLabel = info_lbl -- These three fields are , closureSMRep = sm_rep -- (almost) an info table , closureProf = prof } -- (we don't have an SRT yet) where- name = idName id sm_rep = mkHeapRep profile is_static ptr_wds nonptr_wds (lfClosureType lf_info) prof = mkProfilingInfo profile id val_descr nonptr_wds = tot_wds - ptr_wds@@ -839,6 +839,7 @@ | platformTablesNextToCode platform = toInfoLbl platform . closureInfoLabel | otherwise = toEntryLbl platform . closureInfoLabel +-- | Get the info table label for a *thunk*. mkClosureInfoTableLabel :: Platform -> Id -> LambdaFormInfo -> CLabel mkClosureInfoTableLabel platform id lf_info = case lf_info of
compiler/GHC/StgToCmm/DataCon.hs view
@@ -212,7 +212,8 @@ ; let ticky_name | actually_bound = Just binder | otherwise = Nothing - ; checkConArgsDyn (text "TagCheck failed - con_alloc:" <> ppr binder) con (map fromNonVoid args)+ ; checkConArgsDyn (hang (text "TagCheck failed on constructor application.") 4 $+ text "On binder:" <> ppr binder $$ text "Constructor:" <> ppr con) con (map fromNonVoid args) ; hp_plus_n <- allocDynClosure ticky_name info_tbl lf_info use_cc blame_cc args_w_offsets ; return (mkRhsInit platform reg lf_info hp_plus_n) }
compiler/GHC/StgToCmm/Env.hs view
@@ -17,7 +17,7 @@ bindArgsToRegs, bindToReg, rebindToReg, bindArgToReg, idToReg,- getCgIdInfo,+ getCgIdInfo, getCgInfo_maybe, maybeLetNoEscape, ) where @@ -44,6 +44,9 @@ import GHC.Utils.Panic import GHC.Utils.Panic.Plain +import GHC.Builtin.Names (getUnique)++ ------------------------------------- -- Manipulating CgIdInfo -------------------------------------@@ -149,6 +152,12 @@ else cgLookupPanic id -- Bug }}}++-- | Retrieve cg info for a name if it already exists.+getCgInfo_maybe :: Name -> FCode (Maybe CgIdInfo)+getCgInfo_maybe name+ = do { local_binds <- getBinds -- Try local bindings first+ ; return $ lookupVarEnv_Directly local_binds (getUnique name) } cgLookupPanic :: Id -> FCode a cgLookupPanic id
compiler/GHC/StgToCmm/Expr.hs view
@@ -216,7 +216,7 @@ = do platform <- getPlatform return ( lneIdInfo platform bndr args, code ) where- code = forkLneBody $ withNewTickyCounterLNE (idName bndr) args $ do+ code = forkLneBody $ withNewTickyCounterLNE bndr args $ do { restoreCurrentCostCentre cc_slot ; arg_regs <- bindArgsToRegs args ; void $ noEscapeHeapCheck arg_regs (tickyEnterLNE >> cgExpr body) }@@ -459,7 +459,7 @@ cgCase (StgApp v []) _ (PrimAlt _) alts | isVoidRep (idPrimRep v) -- See Note [Scrutinising VoidRep]- , [(DEFAULT, _, rhs)] <- alts+ , [GenStgAlt{alt_con=DEFAULT, alt_bndrs=_, alt_rhs=rhs}] <- alts = cgExpr rhs {- Note [Dodgy unsafeCoerce 1]@@ -652,9 +652,10 @@ chooseReturnBndrs bndr (PrimAlt _) _alts = assertNonVoidIds [bndr] -chooseReturnBndrs _bndr (MultiValAlt n) [(_, ids, _)]+chooseReturnBndrs _bndr (MultiValAlt n) [alt] = assertPpr (ids `lengthIs` n) (ppr n $$ ppr ids $$ ppr _bndr) $ assertNonVoidIds ids -- 'bndr' is not assigned!+ where ids = alt_bndrs alt chooseReturnBndrs bndr (AlgAlt _) _alts = assertNonVoidIds [bndr] -- Only 'bndr' is assigned@@ -669,11 +670,11 @@ cgAlts :: (GcPlan,ReturnKind) -> NonVoid Id -> AltType -> [CgStgAlt] -> FCode ReturnKind -- At this point the result of the case are in the binders-cgAlts gc_plan _bndr PolyAlt [(_, _, rhs)]- = maybeAltHeapCheck gc_plan (cgExpr rhs)+cgAlts gc_plan _bndr PolyAlt [alt]+ = maybeAltHeapCheck gc_plan (cgExpr $ alt_rhs alt) -cgAlts gc_plan _bndr (MultiValAlt _) [(_, _, rhs)]- = maybeAltHeapCheck gc_plan (cgExpr rhs)+cgAlts gc_plan _bndr (MultiValAlt _) [alt]+ = maybeAltHeapCheck gc_plan (cgExpr $ alt_rhs alt) -- Here bndrs are *already* in scope, so don't rebind them cgAlts gc_plan bndr (PrimAlt _) alts@@ -942,7 +943,7 @@ let base_reg = idToReg platform bndr cg_alt :: CgStgAlt -> FCode (AltCon, CmmAGraphScoped)- cg_alt (con, bndrs, rhs)+ cg_alt GenStgAlt{alt_con=con, alt_bndrs=bndrs, alt_rhs=rhs} = getCodeScoped $ maybeAltHeapCheck gc_plan $ do { _ <- bindConArgs con base_reg (assertNonVoidIds bndrs)
− compiler/GHC/StgToCmm/Expr.hs-boot
@@ -1,7 +0,0 @@-module GHC.StgToCmm.Expr where--import GHC.Cmm.Expr-import GHC.StgToCmm.Monad-import GHC.Types.Literal--cgLit :: Literal -> FCode CmmExpr
compiler/GHC/StgToCmm/Prim.hs view
@@ -1661,7 +1661,7 @@ CmmMachOp (mop rep (wordWidth platform)) [CmmMachOp (mop (wordWidth platform) rep) [arg]] where [arg] = args - -- | These primops are implemented by CallishMachOps, because they sometimes+ -- These primops are implemented by CallishMachOps, because they sometimes -- turn into foreign calls depending on the backend. opCallish :: [CmmExpr] -> CallishMachOp -> PrimopCmmEmit opCallish args prim = opIntoRegs $ \[res] -> emitPrimCall [res] prim args@@ -1683,7 +1683,7 @@ PW4 -> opCallish args callish PW8 -> opTranslate args $ mkMop W64 - -- | Basically a "manual" case, rather than one of the common repetitive forms+ -- Basically a "manual" case, rather than one of the common repetitive forms -- above. The results are a parameter to the returned function so we know the -- choice of variant never depends on them. opCallishHandledLater
compiler/GHC/StgToCmm/TagCheck.hs view
@@ -35,12 +35,14 @@ import GHC.Utils.Panic.Plain (panic) import GHC.Stg.Syntax import GHC.StgToCmm.Closure+import GHC.Cmm.Switch (mkSwitchTargets)+import GHC.Cmm.Info (cmmGetClosureType) import GHC.Types.RepType (dataConRuntimeRepStrictness) import GHC.Types.Basic import GHC.Data.FastString (mkFastString)-import GHC.Cmm.Info (cmmGetClosureType)-import GHC.Cmm.Utils (mkWordCLit) +import qualified Data.Map as M+ -- | Check all arguments marked as already tagged for a function -- are tagged by inserting runtime checks. checkFunctionArgTags :: SDoc -> Id -> [Id] -> FCode ()@@ -91,21 +93,43 @@ -- If there is no tag check if we are dealing with a PAP ; emitLabel lno_tag ; emitComment (mkFastString "closereTypeCheck")- ; align_check <- stgToCmmAlignCheck <$> getStgToCmmConfig- ; profile <- getProfile- ; let closure_ty = cmmGetClosureType profile align_check fun- ; ty_reg <- newTemp (bWord platform)- ; emitAssign (CmmLocal ty_reg) closure_ty- ; emit $ mkCbranch (cmmEqWord platform- (CmmReg $ CmmLocal ty_reg)- (CmmLit $ mkWordCLit platform PAP))- lret lbarf (Just True)+ ; needsArgTag fun lbarf lret ; emitLabel lbarf ; emitBarf ("Tag inference failed on:" ++ onWhat) ; emitLabel lret } +-- | Jump to the first block if the argument closure is subject+-- to tagging requirements. Otherwise jump to the 2nd one.+needsArgTag :: CmmExpr -> BlockId -> BlockId -> FCode ()+needsArgTag closure fail lpass = do+ profile <- getProfile+ align_check <- stgToCmmAlignCheck <$> getStgToCmmConfig+ let clo_ty_e = cmmGetClosureType profile align_check closure+ -- The ENTER macro doesn't evaluate FUN/PAP/BCO objects. So we+ -- have to accept them not being tagged. See #21193+ -- See Note [TagInfo of functions]+ let targets = mkSwitchTargets+ False+ (INVALID_OBJECT, N_CLOSURE_TYPES)+ (Just fail)+ (M.fromList [(PAP,lpass)+ ,(BCO,lpass)+ ,(FUN,lpass)+ ,(FUN_1_0,lpass)+ ,(FUN_0_1,lpass)+ ,(FUN_2_0,lpass)+ ,(FUN_1_1,lpass)+ ,(FUN_0_2,lpass)+ ,(FUN_STATIC,lpass)+ ])++ emit $ mkSwitch clo_ty_e targets++ emit $ mkBranch lpass++ emitArgTagCheck :: SDoc -> [CbvMark] -> [Id] -> FCode () emitArgTagCheck info marks args = whenCheckTags $ do mod <- getModuleName@@ -138,7 +162,7 @@ if taggedCgInfo info then return () else case (cg_loc info) of- CmmLoc loc -> emitTagAssertion (showPprUnsafe msg) loc+ CmmLoc loc -> emitTagAssertion (showPprUnsafe $ msg <+> text "arg:" <> ppr arg) loc LneLoc {} -> panic "LNE-arg" -- Check that argument is properly tagged.
compiler/GHC/StgToCmm/Ticky.hs view
@@ -115,8 +115,6 @@ import GHC.Prelude -import GHC.Driver.Session- import GHC.Platform import GHC.Platform.Profile @@ -135,6 +133,7 @@ import GHC.Cmm.CLabel import GHC.Runtime.Heap.Layout + import GHC.Types.Name import GHC.Types.Id import GHC.Types.Basic@@ -154,6 +153,11 @@ import Data.Maybe import qualified Data.Char import Control.Monad ( when, unless )+import GHC.Types.Id.Info+import GHC.Utils.Trace+import GHC.StgToCmm.Env (getCgInfo_maybe)+import Data.Coerce (coerce)+import GHC.Utils.Json ----------------------------------------------------------------------------- --@@ -161,23 +165,73 @@ -- ----------------------------------------------------------------------------- +-- | Number of arguments for a ticky counter.+--+-- Ticky currently treats args to constructor allocations differently than those for functions/LNE bindings.+tickyArgArity :: TickyClosureType -> Int+tickyArgArity (TickyFun _ _fvs args) = length args+tickyArgArity (TickyLNE args) = length args+tickyArgArity (TickyCon{}) = 0+tickyArgArity (TickyThunk{}) = 0++tickyArgDesc :: TickyClosureType -> String+tickyArgDesc arg_info =+ case arg_info of+ TickyFun _ _fvs args -> map (showTypeCategory . idType . fromNonVoid) args+ TickyLNE args -> map (showTypeCategory . idType . fromNonVoid) args+ TickyThunk{} -> ""+ TickyCon{} -> ""++tickyFvDesc :: TickyClosureType -> String+tickyFvDesc arg_info =+ case arg_info of+ TickyFun _ fvs _args -> map (showTypeCategory . idType . fromNonVoid) fvs+ TickyLNE{} -> ""+ TickyThunk _ _ fvs -> map (showTypeCategory . stgArgType) fvs+ TickyCon{} -> ""++instance ToJson TickyClosureType where+ json info = case info of+ (TickyFun {}) -> mkInfo (tickyFvDesc info) (tickyArgDesc info) "fun"+ (TickyLNE {}) -> mkInfo [] (tickyArgDesc info) "lne"+ (TickyThunk uf _ _) -> mkInfo (tickyFvDesc info) [] ("thk" ++ if uf then "_u" else "")+ (TickyCon{}) -> mkInfo [] [] "con"+ where+ mkInfo :: String -> String -> String -> JsonDoc+ mkInfo fvs args ty =+ JSObject+ [("type", json "entCntr")+ ,("subTy", json ty)+ ,("fvs_c", json (length fvs))+ ,("fvs" , json fvs)+ ,("args", json args)+ ]++tickyEntryDesc :: (SDocContext -> TickyClosureType -> String)+tickyEntryDesc ctxt = renderWithContext ctxt . renderJSON . json+ data TickyClosureType = TickyFun Bool -- True <-> single entry+ [NonVoid Id] -- ^ FVs+ [NonVoid Id] -- ^ Args | TickyCon DataCon -- the allocated constructor+ ConstructorNumber | TickyThunk Bool -- True <-> updateable Bool -- True <-> standard thunk (AP or selector), has no entry counter+ [StgArg] -- ^ FVS, StgArg because for thunks these can also be literals. | TickyLNE+ [NonVoid Id] -- ^ Args -withNewTickyCounterFun :: Bool -> Name -> [NonVoid Id] -> FCode a -> FCode a-withNewTickyCounterFun single_entry = withNewTickyCounter (TickyFun single_entry)+withNewTickyCounterFun :: Bool -> Id -> [NonVoid Id] -> [NonVoid Id] -> FCode a -> FCode a+withNewTickyCounterFun single_entry f fvs args = withNewTickyCounter (TickyFun single_entry fvs args) f -withNewTickyCounterLNE :: Name -> [NonVoid Id] -> FCode a -> FCode a+withNewTickyCounterLNE :: Id -> [NonVoid Id] -> FCode a -> FCode a withNewTickyCounterLNE nm args code = do b <- isEnabled stgToCmmTickyLNE- if not b then code else withNewTickyCounter TickyLNE nm args code+ if not b then code else withNewTickyCounter (TickyLNE args) nm code thunkHasCounter :: Bool -> FCode Bool thunkHasCounter isStatic = (not isStatic &&) <$> isEnabled stgToCmmTickyDynThunk@@ -185,46 +239,50 @@ withNewTickyCounterThunk :: Bool -- ^ static -> Bool -- ^ updateable- -> Name+ -> Id+ -> [NonVoid Id] -- ^ Free vars -> FCode a -> FCode a-withNewTickyCounterThunk isStatic isUpdatable name code = do+withNewTickyCounterThunk isStatic isUpdatable name fvs code = do has_ctr <- thunkHasCounter isStatic if not has_ctr then code- else withNewTickyCounter (TickyThunk isUpdatable False) name [] code+ else withNewTickyCounter (TickyThunk isUpdatable False (map StgVarArg $ coerce fvs)) name code withNewTickyCounterStdThunk :: Bool -- ^ updateable- -> Name+ -> Id+ -> [StgArg] -- ^ Free vars + function -> FCode a -> FCode a-withNewTickyCounterStdThunk isUpdatable name code = do+withNewTickyCounterStdThunk isUpdatable name fvs code = do has_ctr <- thunkHasCounter False if not has_ctr then code- else withNewTickyCounter (TickyThunk isUpdatable True) name [] code+ else withNewTickyCounter (TickyThunk isUpdatable True fvs) name code withNewTickyCounterCon- :: Name+ :: Id -> DataCon+ -> ConstructorNumber -> FCode a -> FCode a-withNewTickyCounterCon name datacon code = do+withNewTickyCounterCon name datacon info code = do has_ctr <- thunkHasCounter False if not has_ctr then code- else withNewTickyCounter (TickyCon datacon) name [] code+ else withNewTickyCounter (TickyCon datacon info) name code -- args does not include the void arguments-withNewTickyCounter :: TickyClosureType -> Name -> [NonVoid Id] -> FCode a -> FCode a-withNewTickyCounter cloType name args m = do- lbl <- emitTickyCounter cloType name args+withNewTickyCounter :: TickyClosureType -> Id -> FCode a -> FCode a+withNewTickyCounter cloType name m = do+ lbl <- emitTickyCounter cloType name setTickyCtrLabel lbl m -emitTickyCounter :: TickyClosureType -> Name -> [NonVoid Id] -> FCode CLabel-emitTickyCounter cloType name args- = let ctr_lbl = mkRednCountsLabel name in+emitTickyCounter :: TickyClosureType -> Id -> FCode CLabel+emitTickyCounter cloType tickee+ = let name = idName tickee in+ let ctr_lbl = mkRednCountsLabel name in (>> return ctr_lbl) $ ifTicky $ do { cfg <- getStgToCmmConfig@@ -239,23 +297,52 @@ ppr_for_ticky_name :: SDoc ppr_for_ticky_name = let ext = case cloType of- TickyFun single_entry -> parens $ hcat $ punctuate comma $+ TickyFun single_entry _ _-> parens $ hcat $ punctuate comma $ [text "fun"] ++ [text "se"|single_entry]- TickyCon datacon -> parens (text "con:" <+> ppr (dataConName datacon))- TickyThunk upd std -> parens $ hcat $ punctuate comma $+ TickyCon datacon _cn -> parens (text "con:" <+> ppr (dataConName datacon))+ TickyThunk upd std _-> parens $ hcat $ punctuate comma $ [text "thk"] ++ [text "se"|not upd] ++ [text "std"|std]- TickyLNE | isInternalName name -> parens (text "LNE")- | otherwise -> panic "emitTickyCounter: how is this an external LNE?"+ TickyLNE _ | isInternalName name -> parens (text "LNE")+ | otherwise -> panic "emitTickyCounter: how is this an external LNE?" p = case hasHaskellName parent of -- NB the default "top" ticky ctr does not -- have a Haskell name Just pname -> text "in" <+> ppr (nameUnique pname) _ -> empty in pprTickyName mod_name name <+> ext <+> p+ ; this_mod <- getModuleName+ ; let t = case cloType of+ TickyCon {} -> "C"+ TickyFun {} -> "F"+ TickyThunk {} -> "T"+ TickyLNE {} -> "L"+ ; info_lbl <- case cloType of+ TickyCon dc mn -> case mn of+ NoNumber -> return $! CmmLabel $ mkConInfoTableLabel (dataConName dc) DefinitionSite+ (Numbered n) -> return $! CmmLabel $ mkConInfoTableLabel (dataConName dc) (UsageSite this_mod n)+ TickyFun {} ->+ return $! CmmLabel $ mkInfoTableLabel name NoCafRefs + TickyThunk _ std_thunk _fvs+ | not std_thunk+ -> return $! CmmLabel $ mkInfoTableLabel name NoCafRefs+ -- IPE Maps have no entry for std thunks.+ | otherwise+ -> do+ lf_info <- getCgInfo_maybe name+ profile <- getProfile+ case lf_info of+ Just (CgIdInfo { cg_lf = cg_lf })+ | isLFThunk cg_lf+ -> return $! CmmLabel $ mkClosureInfoTableLabel (profilePlatform profile) tickee cg_lf+ _ -> pprTraceDebug "tickyThunkUnknown" (text t <> colon <> ppr name <+> ppr (mkInfoTableLabel name NoCafRefs))+ return $! zeroCLit platform++ TickyLNE {} -> return $! zeroCLit platform+ ; let ctx = defaultSDocContext {sdocPprDebug = True} ; fun_descr_lit <- newStringCLit $ renderWithContext ctx ppr_for_ticky_name- ; arg_descr_lit <- newStringCLit $ map (showTypeCategory . idType . fromNonVoid) args+ ; arg_descr_lit <- newStringCLit $ tickyEntryDesc ctx cloType ; emitDataLits ctr_lbl -- Must match layout of rts/include/rts/Ticky.h's StgEntCounter --@@ -263,10 +350,11 @@ -- before, but the code generator wasn't handling that -- properly and it led to chaos, panic and disorder. [ mkIntCLit platform 0, -- registered?- mkIntCLit platform (length args), -- Arity+ mkIntCLit platform (tickyArgArity cloType), -- Arity mkIntCLit platform 0, -- Heap allocated for this thing fun_descr_lit, arg_descr_lit,+ info_lbl, zeroCLit platform, -- Entries into this thing zeroCLit platform, -- Heap allocated by this thing zeroCLit platform -- Link to next StgEntCounter
compiler/GHC/Tc/Deriv.hs view
@@ -88,7 +88,7 @@ 3. Add the derived bindings, generating InstInfos -} -data EarlyDerivSpec = InferTheta (DerivSpec [ThetaOrigin])+data EarlyDerivSpec = InferTheta (DerivSpec ThetaSpec) | GivenTheta (DerivSpec ThetaType) -- InferTheta ds => the context for the instance should be inferred -- In this case ds_theta is the list of all the sets of@@ -102,7 +102,7 @@ -- See Note [Inferring the instance context] in GHC.Tc.Deriv.Infer splitEarlyDerivSpec :: [EarlyDerivSpec]- -> ([DerivSpec [ThetaOrigin]], [DerivSpec ThetaType])+ -> ([DerivSpec ThetaSpec], [DerivSpec ThetaType]) splitEarlyDerivSpec [] = ([],[]) splitEarlyDerivSpec (InferTheta spec : specs) = case splitEarlyDerivSpec specs of (is, gs) -> (spec : is, gs)@@ -197,72 +197,67 @@ ; traceTc "tcDeriving" (ppr early_specs) ; let (infer_specs, given_specs) = splitEarlyDerivSpec early_specs- ; insts1 <- mapM genInst given_specs- ; insts2 <- mapM genInst infer_specs+ ; famInsts1 <- concatMapM genFamInsts given_specs+ ; famInsts2 <- concatMapM genFamInsts infer_specs+ ; let famInsts = famInsts1 ++ famInsts2 ; dflags <- getDynFlags ; logger <- getLogger - ; let (_, deriv_stuff, fvs) = unzip3 (insts1 ++ insts2)- ; loc <- getSrcSpanM- ; let (binds, famInsts) = genAuxBinds dflags loc- (unionManyBags deriv_stuff)-- ; let mk_inst_infos1 = map fstOf3 insts1- ; inst_infos1 <- apply_inst_infos mk_inst_infos1 given_specs- -- We must put all the derived type family instances (from both -- infer_specs and given_specs) in the local instance environment -- before proceeding, or else simplifyInstanceContexts might -- get stuck if it has to reason about any of those family instances. -- See Note [Staging of tcDeriving]- ; tcExtendLocalFamInstEnv (bagToList famInsts) $+ ; tcExtendLocalFamInstEnv famInsts $ -- NB: only call tcExtendLocalFamInstEnv once, as it performs -- validity checking for all of the family instances you give it. -- If the family instances have errors, calling it twice will result -- in duplicate error messages! - do {- -- the stand-alone derived instances (@inst_infos1@) are used when+ do { given_inst_binds <- mapM genInstBinds given_specs++ ; let given_inst_infos = map fstOf3 given_inst_binds++ -- the stand-alone derived instances (@given_inst_infos@) are used when -- inferring the contexts for "deriving" clauses' instances -- (@infer_specs@)- ; final_specs <- extendLocalInstEnv (map iSpec inst_infos1) $- simplifyInstanceContexts infer_specs+ ; final_infer_specs <-+ extendLocalInstEnv (map iSpec given_inst_infos) $+ simplifyInstanceContexts infer_specs+ ; infer_inst_binds <- mapM genInstBinds final_infer_specs - ; let mk_inst_infos2 = map fstOf3 insts2- ; inst_infos2 <- apply_inst_infos mk_inst_infos2 final_specs- ; let inst_infos = inst_infos1 ++ inst_infos2+ ; let (_, aux_specs, fvs) = unzip3 (given_inst_binds ++ infer_inst_binds)+ ; loc <- getSrcSpanM+ ; let aux_binds = genAuxBinds dflags loc (unionManyBags aux_specs) - ; (inst_info, rn_binds, rn_dus) <- renameDeriv inst_infos binds+ ; let infer_inst_infos = map fstOf3 infer_inst_binds+ ; let inst_infos = given_inst_infos ++ infer_inst_infos + ; (inst_info, rn_aux_binds, rn_dus) <- renameDeriv inst_infos aux_binds+ ; unless (isEmptyBag inst_info) $ liftIO (putDumpFileMaybe logger Opt_D_dump_deriv "Derived instances" FormatHaskell- (ddump_deriving inst_info rn_binds famInsts))+ (ddump_deriving inst_info rn_aux_binds famInsts)) ; gbl_env <- tcExtendLocalInstEnv (map iSpec (bagToList inst_info)) getGblEnv ; let all_dus = rn_dus `plusDU` usesOnly (NameSet.mkFVs $ concat fvs)- ; return (addTcgDUs gbl_env all_dus, inst_info, rn_binds) } }+ ; return (addTcgDUs gbl_env all_dus, inst_info, rn_aux_binds) } } where ddump_deriving :: Bag (InstInfo GhcRn) -> HsValBinds GhcRn- -> Bag FamInst -- ^ Rep type family instances+ -> [FamInst] -- Associated type family instances -> SDoc- ddump_deriving inst_infos extra_binds repFamInsts+ ddump_deriving inst_infos extra_binds famInsts = hang (text "Derived class instances:") 2 (vcat (map (\i -> pprInstInfoDetails i $$ text "") (bagToList inst_infos)) $$ ppr extra_binds) $$ hangP (text "Derived type family instances:")- (vcat (map pprRepTy (bagToList repFamInsts)))+ (vcat (map pprRepTy famInsts)) hangP s x = text "" $$ hang s 2 x - -- Apply the suspended computations given by genInst calls.- -- See Note [Staging of tcDeriving]- apply_inst_infos :: [ThetaType -> TcM (InstInfo GhcPs)]- -> [DerivSpec ThetaType] -> TcM [InstInfo GhcPs]- apply_inst_infos = zipWithM (\f ds -> f (ds_theta ds))- -- Prints the representable type family instance pprRepTy :: FamInst -> SDoc pprRepTy fi@(FamInst { fi_tys = lhs })@@ -359,32 +354,18 @@ it needed in the environment in order to properly simplify instance like the C N instance above. -To avoid this scenario, we carefully structure the order of events in-tcDeriving. We first call genInst on the standalone derived instance specs and-the instance specs obtained from deriving clauses. Note that the return type of-genInst is a triple:-- TcM (ThetaType -> TcM (InstInfo RdrName), BagDerivStuff, Maybe Name)--The type family instances are in the BagDerivStuff. The first field of the-triple is a suspended computation which, given an instance context, produces-the rest of the instance. The fact that it is suspended is important, because-right now, we don't have ThetaTypes for the instances that use deriving clauses-(only the standalone-derived ones).--Now we can collect the type family instances and extend the local instance-environment. At this point, it is safe to run simplifyInstanceContexts on the-deriving-clause instance specs, which gives us the ThetaTypes for the-deriving-clause instances. Now we can feed all the ThetaTypes to the-suspended computations and obtain our InstInfos, at which point-tcDeriving is done.+To avoid this scenario, we generate things in tcDeriving in a specific order: -An alternative design would be to split up genInst so that the-family instances are generated separately from the InstInfos. But this would-require carving up a lot of the GHC deriving internals to accommodate the-change. On the other hand, we can keep all of the InstInfo and type family-instance logic together in genInst simply by converting genInst to-continuation-returning style, so we opt for that route.+1. First, we generate all of the associated type family instances for derived+ instances (using `genFamInsts`).+2. Next, we extend the local instance environment with these type family+ instances.+3. Then, we generate the instance bindings for derived instances+ (using `genInstBinds`).+4. Finally, for instances generated with `deriving` clauses, we infer the+ instance contexts (using `simplifyInstanceContexts`). At this point, we+ already have the necessary type family instances in scope (from step (2)),+ so this is safe to do. Note [Why we don't pass rep_tc into deriveTyData] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -1156,14 +1137,40 @@ mkEqnHelp overlap_mode tvs cls cls_args deriv_ctxt deriv_strat = do is_boot <- tcIsHsBootOrSig when is_boot $ bale_out DerivErrBootFileFound++ let pred = mkClassPred cls cls_args+ skol_info <- mkSkolemInfo (DerivSkol pred)+ (tvs', cls_args', deriv_strat') <-+ skolemise_when_inferring_context skol_info deriv_ctxt+ let deriv_env = DerivEnv+ { denv_overlap_mode = overlap_mode+ , denv_tvs = tvs'+ , denv_cls = cls+ , denv_inst_tys = cls_args'+ , denv_ctxt = deriv_ctxt+ , denv_skol_info = skol_info+ , denv_strat = deriv_strat' } runReaderT mk_eqn deriv_env where- deriv_env = DerivEnv { denv_overlap_mode = overlap_mode- , denv_tvs = tvs- , denv_cls = cls- , denv_inst_tys = cls_args- , denv_ctxt = deriv_ctxt- , denv_strat = deriv_strat }+ skolemise_when_inferring_context ::+ SkolemInfo -> DerivContext+ -> TcM ([TcTyVar], [TcType], Maybe (DerivStrategy GhcTc))+ skolemise_when_inferring_context skol_info deriv_ctxt =+ case deriv_ctxt of+ -- In order to infer an instance context, we must later make use of+ -- the constraint solving machinery, which expects TcTyVars rather+ -- than TyVars. We skolemise the type variables with non-overlappable+ -- (vanilla) skolems.+ -- See Note [Overlap and deriving] in GHC.Tc.Deriv.Infer.+ InferContext{} -> do+ (skol_subst, tvs') <- tcInstSkolTyVars skol_info tvs+ let cls_args' = substTys skol_subst cls_args+ deriv_strat' = fmap (mapDerivStrategy (substTy skol_subst))+ deriv_strat+ pure (tvs', cls_args', deriv_strat')+ -- If the instance context is supplied, we don't need to skolemise+ -- at all.+ SupplyContext{} -> pure (tvs, cls_args, deriv_strat) bale_out = failWithTc . TcRnCannotDeriveInstance cls cls_args deriv_strat NoGeneralizedNewtypeDeriving@@ -1327,7 +1334,9 @@ , denv_tvs = tvs , denv_cls = cls , denv_inst_tys = inst_tys- , denv_ctxt = deriv_ctxt } <- ask+ , denv_ctxt = deriv_ctxt+ , denv_skol_info = skol_info } <- ask+ user_ctxt <- askDerivUserTypeCtxt doDerivInstErrorChecks1 mechanism loc <- lift getSrcSpanM dfun_name <- lift $ newDFunName cls inst_tys loc@@ -1340,6 +1349,8 @@ , ds_name = dfun_name, ds_tvs = tvs' , ds_cls = cls, ds_tys = inst_tys' , ds_theta = inferred_constraints+ , ds_skol_info = skol_info+ , ds_user_ctxt = user_ctxt , ds_overlap = overlap_mode , ds_standalone_wildcard = wildcard , ds_mechanism = mechanism' } }@@ -1350,6 +1361,8 @@ , ds_name = dfun_name, ds_tvs = tvs , ds_cls = cls, ds_tys = inst_tys , ds_theta = theta+ , ds_skol_info = skol_info+ , ds_user_ctxt = user_ctxt , ds_overlap = overlap_mode , ds_standalone_wildcard = Nothing , ds_mechanism = mechanism }@@ -1361,17 +1374,17 @@ let isDeriveAnyClassEnabled = deriveAnyClassEnabled (xopt LangExt.DeriveAnyClass dflags) checkOriginativeSideConditions dit >>= \case- CanDeriveStock gen_fn -> mk_eqn_from_mechanism $- DerivSpecStock { dsm_stock_dit = dit- , dsm_stock_gen_fn = gen_fn }- StockClassError why -> derivingThingFailWith NoGeneralizedNewtypeDeriving why- CanDeriveAnyClass -> derivingThingFailWith NoGeneralizedNewtypeDeriving- (DerivErrNotStockDeriveable isDeriveAnyClassEnabled)+ CanDeriveStock gen_fns -> mk_eqn_from_mechanism $+ DerivSpecStock { dsm_stock_dit = dit+ , dsm_stock_gen_fns = gen_fns }+ StockClassError why -> derivingThingFailWith NoGeneralizedNewtypeDeriving why+ CanDeriveAnyClass -> derivingThingFailWith NoGeneralizedNewtypeDeriving+ (DerivErrNotStockDeriveable isDeriveAnyClassEnabled) -- In the 'NonDerivableClass' case we can't derive with either stock or anyclass -- so we /don't want/ to suggest the user to enabled 'DeriveAnyClass', that's -- why we pass 'YesDeriveAnyClassEnabled', so that GHC won't attempt to suggest it.- NonDerivableClass -> derivingThingFailWith NoGeneralizedNewtypeDeriving- (DerivErrNotStockDeriveable YesDeriveAnyClassEnabled)+ NonDerivableClass -> derivingThingFailWith NoGeneralizedNewtypeDeriving+ (DerivErrNotStockDeriveable YesDeriveAnyClassEnabled) mk_eqn_anyclass :: DerivM EarlyDerivSpec mk_eqn_anyclass@@ -1446,12 +1459,12 @@ = DerivErrNotStockDeriveable isDeriveAnyClassEnabled checkOriginativeSideConditions dit >>= \case- NonDerivableClass -> derivingThingFailWith NoGeneralizedNewtypeDeriving dac_error- StockClassError why -> derivingThingFailWith NoGeneralizedNewtypeDeriving why- CanDeriveStock gen_fn -> mk_eqn_from_mechanism $- DerivSpecStock { dsm_stock_dit = dit- , dsm_stock_gen_fn = gen_fn }- CanDeriveAnyClass -> mk_eqn_from_mechanism DerivSpecAnyClass+ NonDerivableClass -> derivingThingFailWith NoGeneralizedNewtypeDeriving dac_error+ StockClassError why -> derivingThingFailWith NoGeneralizedNewtypeDeriving why+ CanDeriveStock gen_fns -> mk_eqn_from_mechanism $+ DerivSpecStock { dsm_stock_dit = dit+ , dsm_stock_gen_fns = gen_fns }+ CanDeriveAnyClass -> mk_eqn_from_mechanism DerivSpecAnyClass {- ************************************************************************@@ -1607,9 +1620,9 @@ $ TcRnDerivingDefaults cls mk_eqn_from_mechanism DerivSpecAnyClass -- CanDeriveStock- CanDeriveStock gen_fn -> mk_eqn_from_mechanism $- DerivSpecStock { dsm_stock_dit = dit- , dsm_stock_gen_fn = gen_fn }+ CanDeriveStock gen_fns -> mk_eqn_from_mechanism $+ DerivSpecStock { dsm_stock_dit = dit+ , dsm_stock_gen_fns = gen_fns } {- Note [Recursive newtypes]@@ -1816,32 +1829,31 @@ \end{itemize} -} --- Generate the InstInfo for the required instance--- plus any auxiliary bindings required-genInst :: DerivSpec theta- -> TcM (ThetaType -> TcM (InstInfo GhcPs), BagDerivStuff, [Name])--- We must use continuation-returning style here to get the order in which we--- typecheck family instances and derived instances right.--- See Note [Staging of tcDeriving]-genInst spec@(DS { ds_tvs = tvs, ds_mechanism = mechanism- , ds_tys = tys, ds_cls = clas, ds_loc = loc- , ds_standalone_wildcard = wildcard })- = do (meth_binds, meth_sigs, deriv_stuff, unusedNames)- <- set_span_and_ctxt $- genDerivStuff mechanism loc clas tys tvs- let mk_inst_info theta = set_span_and_ctxt $ do- inst_spec <- newDerivClsInst theta spec- doDerivInstErrorChecks2 clas inst_spec theta wildcard mechanism- traceTc "newder" (ppr inst_spec)- return $ InstInfo- { iSpec = inst_spec- , iBinds = InstBindings- { ib_binds = meth_binds- , ib_tyvars = map Var.varName tvs- , ib_pragmas = meth_sigs- , ib_extensions = extensions- , ib_derived = True } }- return (mk_inst_info, deriv_stuff, unusedNames)+-- | Generate the 'InstInfo' for the required instance,+-- plus any auxiliary bindings required (see @Note [Auxiliary binders]@ in+-- "GHC.Tc.Deriv.Generate") and any additional free variables+-- that should be marked (see @Note [Deriving and unused record selectors]@+-- in "GHC.Tc.Deriv.Utils").+genInstBinds :: DerivSpec ThetaType+ -> TcM (InstInfo GhcPs, Bag AuxBindSpec, [Name])+genInstBinds spec@(DS { ds_tvs = tyvars, ds_mechanism = mechanism+ , ds_tys = inst_tys, ds_theta = theta, ds_cls = clas+ , ds_loc = loc, ds_standalone_wildcard = wildcard })+ = set_spec_span_and_ctxt spec $+ do (meth_binds, meth_sigs, aux_specs, unusedNames) <- gen_inst_binds+ inst_spec <- newDerivClsInst spec+ doDerivInstErrorChecks2 clas inst_spec theta wildcard mechanism+ traceTc "newder" (ppr inst_spec)+ let inst_info =+ InstInfo+ { iSpec = inst_spec+ , iBinds = InstBindings+ { ib_binds = meth_binds+ , ib_tyvars = map Var.varName tyvars+ , ib_pragmas = meth_sigs+ , ib_extensions = extensions+ , ib_derived = True } }+ return (inst_info, aux_specs, unusedNames) where extensions :: [LangExt.Extension] extensions@@ -1860,9 +1872,76 @@ | otherwise = [] - set_span_and_ctxt :: TcM a -> TcM a- set_span_and_ctxt = setSrcSpan loc . addErrCtxt (instDeclCtxt3 clas tys)+ gen_inst_binds :: TcM (LHsBinds GhcPs, [LSig GhcPs], Bag AuxBindSpec, [Name])+ gen_inst_binds+ = case mechanism of+ -- See Note [Bindings for Generalised Newtype Deriving]+ DerivSpecNewtype { dsm_newtype_rep_ty = rhs_ty}+ -> gen_newtype_or_via rhs_ty + -- Try a stock deriver+ DerivSpecStock { dsm_stock_dit = dit+ , dsm_stock_gen_fns =+ StockGenFns { stock_gen_binds = gen_fn } }+ -> gen_fn loc dit++ -- Try DeriveAnyClass+ DerivSpecAnyClass+ -> return (emptyBag, [], emptyBag, [])+ -- No method bindings, signatures, auxiliary bindings or free+ -- variable names are needed. The only interesting work happens when+ -- defaulting associated type family instances (see the+ -- DeriveSpecAnyClass case in genFamInsts below).++ -- Try DerivingVia+ DerivSpecVia{dsm_via_ty = via_ty}+ -> gen_newtype_or_via via_ty++ gen_newtype_or_via ty = do+ let (binds, sigs) = gen_Newtype_binds loc clas tyvars inst_tys ty+ return (binds, sigs, emptyBag, [])++-- | Generate the associated type family instances for a derived instance.+genFamInsts :: DerivSpec theta -> TcM [FamInst]+genFamInsts spec@(DS { ds_tvs = tyvars, ds_mechanism = mechanism+ , ds_tys = inst_tys, ds_cls = clas, ds_loc = loc })+ = set_spec_span_and_ctxt spec $+ case mechanism of+ -- See Note [GND and associated type families]+ DerivSpecNewtype { dsm_newtype_rep_ty = rhs_ty}+ -> gen_newtype_or_via rhs_ty++ -- Try a stock deriver+ DerivSpecStock { dsm_stock_dit = dit+ , dsm_stock_gen_fns =+ StockGenFns { stock_gen_fam_insts = gen_fn } }+ -> gen_fn loc dit++ -- See Note [DeriveAnyClass and default family instances]+ DerivSpecAnyClass -> do+ let mini_env = mkVarEnv (classTyVars clas `zip` inst_tys)+ mini_subst = mkTvSubst (mkInScopeSet (mkVarSet tyvars)) mini_env+ dflags <- getDynFlags+ tyfam_insts <-+ -- canDeriveAnyClass should ensure that this code can't be reached+ -- unless -XDeriveAnyClass is enabled.+ assertPpr (xopt LangExt.DeriveAnyClass dflags)+ (ppr "genFamInsts: bad derived class" <+> ppr clas) $+ mapM (tcATDefault loc mini_subst emptyNameSet)+ (classATItems clas)+ pure $ concat tyfam_insts++ -- Try DerivingVia+ DerivSpecVia{dsm_via_ty = via_ty}+ -> gen_newtype_or_via via_ty+ where+ gen_newtype_or_via ty = gen_Newtype_fam_insts loc clas tyvars inst_tys ty++-- Set the SrcSpan and error context for an action that uses a DerivSpec.+set_spec_span_and_ctxt :: DerivSpec theta -> TcM a -> TcM a+set_spec_span_and_ctxt (DS{ ds_loc = loc, ds_cls = clas, ds_tys = tys }) =+ setSrcSpan loc . addErrCtxt (instDeclCtxt3 clas tys)+ -- Checks: -- -- * All of the data constructors for a data type are in scope for a@@ -2004,47 +2083,6 @@ err <- derivingThingErrM newtype_deriving msg lift $ failWithTc err -genDerivStuff :: DerivSpecMechanism -> SrcSpan -> Class- -> [Type] -> [TyVar]- -> TcM (LHsBinds GhcPs, [LSig GhcPs], BagDerivStuff, [Name])-genDerivStuff mechanism loc clas inst_tys tyvars- = case mechanism of- -- See Note [Bindings for Generalised Newtype Deriving]- DerivSpecNewtype { dsm_newtype_rep_ty = rhs_ty}- -> gen_newtype_or_via rhs_ty-- -- Try a stock deriver- DerivSpecStock { dsm_stock_dit = dit- , dsm_stock_gen_fn = gen_fn }- -> gen_fn loc inst_tys dit-- -- Try DeriveAnyClass- DerivSpecAnyClass -> do- let mini_env = mkVarEnv (classTyVars clas `zip` inst_tys)- mini_subst = mkTvSubst (mkInScopeSet (mkVarSet tyvars)) mini_env- dflags <- getDynFlags- tyfam_insts <-- -- canDeriveAnyClass should ensure that this code can't be reached- -- unless -XDeriveAnyClass is enabled.- assertPpr (xopt LangExt.DeriveAnyClass dflags)- (ppr "genDerivStuff: bad derived class" <+> ppr clas) $- mapM (tcATDefault loc mini_subst emptyNameSet)- (classATItems clas)- return ( emptyBag, [] -- No method bindings are needed...- , listToBag (map DerivFamInst (concat tyfam_insts))- -- ...but we may need to generate binding for associated type- -- family default instances.- -- See Note [DeriveAnyClass and default family instances]- , [] )-- -- Try DerivingVia- DerivSpecVia{dsm_via_ty = via_ty}- -> gen_newtype_or_via via_ty- where- gen_newtype_or_via ty = do- (binds, sigs, faminsts) <- gen_Newtype_binds loc clas tyvars inst_tys ty- return (binds, sigs, faminsts, [])- {- Note [Bindings for Generalised Newtype Deriving] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -2058,7 +2096,7 @@ instance (C [a], Eq a) => C (N a) where f = coerce (f :: [a] -> [a]) -This generates a cast for each method, but allows the superclasse to+This generates a cast for each method, but allows the superclasses to be worked out in the usual way. In this case the superclass (Eq (N a)) will be solved by the explicit Eq (N a) instance. We do *not* create the superclasses by casting the superclass dictionaries for the
compiler/GHC/Tc/Deriv/Functor.hs view
@@ -149,7 +149,7 @@ $(coreplace 'a '(tb -> tc) x) = \(y:tb[b/a]) -> $(coreplace 'a' 'tc' (x $(replace 'a 'tb y))) -} -gen_Functor_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, BagDerivStuff)+gen_Functor_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, Bag AuxBindSpec) -- When the argument is phantom, we can use fmap _ = coerce -- See Note [Phantom types with Functor, Foldable, and Traversable] gen_Functor_binds loc (DerivInstTys{dit_rep_tc = tycon})@@ -784,7 +784,7 @@ think it's okay to do it for now. -} -gen_Foldable_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, BagDerivStuff)+gen_Foldable_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, Bag AuxBindSpec) -- When the parameter is phantom, we can use foldMap _ _ = mempty -- See Note [Phantom types with Functor, Foldable, and Traversable] gen_Foldable_binds loc (DerivInstTys{dit_rep_tc = tycon})@@ -1018,7 +1018,7 @@ See Note [Generated code for DeriveFoldable and DeriveTraversable]. -} -gen_Traversable_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, BagDerivStuff)+gen_Traversable_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, Bag AuxBindSpec) -- When the argument is phantom, we can use traverse = pure . coerce -- See Note [Phantom types with Functor, Foldable, and Traversable] gen_Traversable_binds loc (DerivInstTys{dit_rep_tc = tycon})
compiler/GHC/Tc/Deriv/Generate.hs view
@@ -19,7 +19,7 @@ -- -- This is where we do all the grimy bindings' generation. module GHC.Tc.Deriv.Generate (- BagDerivStuff, DerivStuff(..),+ AuxBindSpec(..), gen_Eq_binds, gen_Ord_binds,@@ -31,6 +31,7 @@ gen_Data_binds, gen_Lift_binds, gen_Newtype_binds,+ gen_Newtype_fam_insts, mkCoerceClassMethEqn, genAuxBinds, ordOpTbl, boxConTbl, litConTbl,@@ -38,7 +39,7 @@ getPossibleDataCons, DerivInstTys(..), buildDataConInstArgEnv,- derivDataConInstArgTys, substDerivInstTys+ derivDataConInstArgTys, substDerivInstTys, zonkDerivInstTys ) where import GHC.Prelude@@ -64,6 +65,7 @@ import GHC.Core.TyCon import GHC.Tc.Utils.Env import GHC.Tc.Utils.TcType+import GHC.Tc.Utils.Zonk import GHC.Tc.Validity ( checkValidCoAxBranch ) import GHC.Core.Coercion.Axiom ( coAxiomSingleBranch ) import GHC.Builtin.Types.Prim@@ -87,8 +89,6 @@ import GHC.Data.Maybe ( expectJust ) import GHC.Unit.Module -type BagDerivStuff = Bag DerivStuff- -- | A declarative description of an auxiliary binding that should be -- generated. See @Note [Auxiliary binders]@ for a more detailed description -- of how these are used.@@ -138,23 +138,6 @@ auxBindSpecRdrName (DerivDataDataType _ dataT_RDR _) = dataT_RDR auxBindSpecRdrName (DerivDataConstr _ dataC_RDR _) = dataC_RDR -data DerivStuff -- Please add this auxiliary stuff- = DerivAuxBind AuxBindSpec- -- ^ A new, top-level auxiliary binding. Used for deriving 'Eq', 'Ord',- -- 'Enum', 'Ix', and 'Data'. See Note [Auxiliary binders].-- -- Generics and DeriveAnyClass- | DerivFamInst FamInst -- New type family instances- -- ^ A new type family instance. Used for:- --- -- * @DeriveGeneric@, which generates instances of @Rep(1)@- --- -- * @DeriveAnyClass@, which can fill in associated type family defaults- --- -- * @GeneralizedNewtypeDeriving@, which generates instances of associated- -- type families for newtypes-- {- ************************************************************************ * *@@ -170,6 +153,12 @@ data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ... +* We first attempt to compare the constructor tags. If tags don't+ match - we immediately bail out. Otherwise, we then generate one+ branch per constructor comparing only the fields as we already+ know that the tags match. Note that it only makes sense to check+ the tag if there is more than one data constructor.+ * For the ordinary constructors (if any), we emit clauses to do The Usual Thing, e.g.,: @@ -182,23 +171,29 @@ case (a1 `eqFloat#` a2) of r -> r for that particular test. -* For nullary constructors, we emit a- catch-all clause of the form:+* For nullary constructors, we emit a catch-all clause that always+ returns True since we already know that the tags match. - (==) a b = case (dataToTag# a) of { a# ->- case (dataToTag# b) of { b# ->- case (a# ==# b#) of {- r -> r }}}+* So, given this data type: + data T = A | B Int | C Char++ We roughly get:++ (==) a b =+ case dataToTag# a /= dataToTag# b of+ True -> False+ False -> case a of -- Here we already know that tags match+ B a1 -> case b of+ B b1 -> a1 == b1 -- Only one branch+ C a1 -> case b of+ C b1 -> a1 == b1 -- Only one branch+ _ -> True -- catch-all to match all nullary ctors+ An older approach preferred regular pattern matches in some cases but with dataToTag# forcing it's argument, and work on improving join points, this seems no longer necessary. -* If there aren't any nullary constructors, we emit a simpler- catch-all:-- (==) a b = False- * For the @(/=)@ method, we normally just use the default method. If the type is an enumeration type, we could/may/should? generate special code that calls @dataToTag#@, much like for @(==)@ shown@@ -214,65 +209,75 @@ produced don't get through the typechecker. -} -gen_Eq_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, BagDerivStuff)+gen_Eq_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, Bag AuxBindSpec) gen_Eq_binds loc dit@(DerivInstTys{ dit_rep_tc = tycon , dit_rep_tc_args = tycon_args }) = do return (method_binds, emptyBag) where all_cons = getPossibleDataCons tycon tycon_args- (nullary_cons, non_nullary_cons) = partition isNullarySrcDataCon all_cons-- -- For nullary constructors, use the getTag stuff.- (tag_match_cons, pat_match_cons) = (nullary_cons, non_nullary_cons)- no_tag_match_cons = null tag_match_cons-- -- (LHS patterns, result)- fall_through_eqn :: [([LPat (GhcPass 'Parsed)] , LHsExpr GhcPs)]- fall_through_eqn- | no_tag_match_cons -- All constructors have arguments- = case pat_match_cons of- [] -> [] -- No constructors; no fall-though case- [_] -> [] -- One constructor; no fall-though case- _ -> -- Two or more constructors; add fall-through of- -- (==) _ _ = False- [([nlWildPat, nlWildPat], false_Expr)]+ non_nullary_cons = filter (not . isNullarySrcDataCon) all_cons - | otherwise -- One or more tag_match cons; add fall-through of- -- extract tags compare for equality,- -- The case `(C1 x) == (C1 y)` can no longer happen- -- at this point as it's matched earlier.- = [([a_Pat, b_Pat],- untag_Expr [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]- (genPrimOpApp (nlHsVar ah_RDR) eqInt_RDR (nlHsVar bh_RDR)))]+ -- Generate tag check. See #17240+ eq_expr_with_tag_check = nlHsCase+ (nlHsPar (untag_Expr [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]+ (nlHsOpApp (nlHsVar ah_RDR) neInt_RDR (nlHsVar bh_RDR))))+ [ mkHsCaseAlt (nlLitPat (HsIntPrim NoSourceText 1)) false_Expr+ , mkHsCaseAlt nlWildPat (+ nlHsCase+ (nlHsVar a_RDR)+ -- Only one branch to match all nullary constructors+ -- as we already know the tags match but do not emit+ -- the branch if there are no nullary constructors+ (let non_nullary_pats = map pats_etc non_nullary_cons+ in if null non_nullary_cons+ then non_nullary_pats+ else non_nullary_pats ++ [mkHsCaseAlt nlWildPat true_Expr]))+ ] method_binds = unitBag eq_bind- eq_bind- = mkFunBindEC 2 loc eq_RDR (const true_Expr)- (map pats_etc pat_match_cons- ++ fall_through_eqn)+ eq_bind = mkFunBindEC 2 loc eq_RDR (const true_Expr) binds+ where+ binds+ | null all_cons = []+ -- Tag checking is redundant when there is only one data constructor+ | [data_con] <- all_cons+ , (as_needed, bs_needed, tys_needed) <- gen_con_fields_and_tys data_con+ , data_con_RDR <- getRdrName data_con+ , con1_pat <- nlParPat $ nlConVarPat data_con_RDR as_needed+ , con2_pat <- nlParPat $ nlConVarPat data_con_RDR bs_needed+ , eq_expr <- nested_eq_expr tys_needed as_needed bs_needed+ = [([con1_pat, con2_pat], eq_expr)]+ -- This is an enum (all constructors are nullary) - just do a simple tag check+ | all isNullarySrcDataCon all_cons+ = [([a_Pat, b_Pat], untag_Expr [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]+ (genPrimOpApp (nlHsVar ah_RDR) eqInt_RDR (nlHsVar bh_RDR)))]+ | otherwise+ = [([a_Pat, b_Pat], eq_expr_with_tag_check)] ------------------------------------------------------------------- pats_etc data_con- = let- con1_pat = nlParPat $ nlConVarPat data_con_RDR as_needed- con2_pat = nlParPat $ nlConVarPat data_con_RDR bs_needed-- data_con_RDR = getRdrName data_con- con_arity = length tys_needed- as_needed = take con_arity as_RDRs- bs_needed = take con_arity bs_RDRs- tys_needed = derivDataConInstArgTys data_con dit- in- ([con1_pat, con2_pat], nested_eq_expr tys_needed as_needed bs_needed)+ nested_eq_expr [] [] [] = true_Expr+ nested_eq_expr tys as bs+ = foldr1 and_Expr (zipWith3Equal "nested_eq" nested_eq tys as bs)+ -- Using 'foldr1' here ensures that the derived code is correctly+ -- associated. See #10859. where- nested_eq_expr [] [] [] = true_Expr- nested_eq_expr tys as bs- = foldr1 and_Expr (zipWith3Equal "nested_eq" nested_eq tys as bs)- -- Using 'foldr1' here ensures that the derived code is correctly- -- associated. See #10859.- where- nested_eq ty a b = nlHsPar (eq_Expr ty (nlHsVar a) (nlHsVar b))+ nested_eq ty a b = nlHsPar (eq_Expr ty (nlHsVar a) (nlHsVar b)) + gen_con_fields_and_tys data_con+ | tys_needed <- derivDataConInstArgTys data_con dit+ , con_arity <- length tys_needed+ , as_needed <- take con_arity as_RDRs+ , bs_needed <- take con_arity bs_RDRs+ = (as_needed, bs_needed, tys_needed)++ pats_etc data_con+ | (as_needed, bs_needed, tys_needed) <- gen_con_fields_and_tys data_con+ , data_con_RDR <- getRdrName data_con+ , con1_pat <- nlParPat $ nlConVarPat data_con_RDR as_needed+ , con2_pat <- nlParPat $ nlConVarPat data_con_RDR bs_needed+ , fields_eq_expr <- nested_eq_expr tys_needed as_needed bs_needed+ = mkHsCaseAlt con1_pat (nlHsCase (nlHsVar b_RDR) [mkHsCaseAlt con2_pat fields_eq_expr])+ {- ************************************************************************ * *@@ -391,7 +396,7 @@ gtResult OrdGT = true_Expr -------------gen_Ord_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, BagDerivStuff)+gen_Ord_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, Bag AuxBindSpec) gen_Ord_binds loc dit@(DerivInstTys{ dit_rep_tc = tycon , dit_rep_tc_args = tycon_args }) = do return $ if null tycon_data_cons -- No data-cons => invoke bale-out case@@ -640,7 +645,7 @@ For @enumFromTo@ and @enumFromThenTo@, we use the default methods. -} -gen_Enum_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, BagDerivStuff)+gen_Enum_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, Bag AuxBindSpec) gen_Enum_binds loc (DerivInstTys{dit_rep_tc = tycon}) = do -- See Note [Auxiliary binders] tag2con_RDR <- new_tag2con_rdr_name loc tycon@@ -657,7 +662,7 @@ , enum_from_then tag2con_RDR maxtag_RDR -- [0, 1 ..] , from_enum ]- aux_binds tag2con_RDR maxtag_RDR = listToBag $ map DerivAuxBind+ aux_binds tag2con_RDR maxtag_RDR = listToBag [ DerivTag2Con tycon tag2con_RDR , DerivMaxTag tycon maxtag_RDR ]@@ -730,7 +735,7 @@ ************************************************************************ -} -gen_Bounded_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, BagDerivStuff)+gen_Bounded_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, Bag AuxBindSpec) gen_Bounded_binds loc (DerivInstTys{dit_rep_tc = tycon}) | isEnumerationTyCon tycon = (listToBag [ min_bound_enum, max_bound_enum ], emptyBag)@@ -817,14 +822,14 @@ (p.~147). -} -gen_Ix_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, BagDerivStuff)+gen_Ix_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, Bag AuxBindSpec) gen_Ix_binds loc (DerivInstTys{dit_rep_tc = tycon}) = do -- See Note [Auxiliary binders] tag2con_RDR <- new_tag2con_rdr_name loc tycon return $ if isEnumerationTyCon tycon- then (enum_ixes tag2con_RDR, listToBag $ map DerivAuxBind+ then (enum_ixes tag2con_RDR, listToBag [ DerivTag2Con tycon tag2con_RDR ]) else (single_con_ixes, emptyBag)@@ -1020,7 +1025,7 @@ -} gen_Read_binds :: (Name -> Fixity) -> SrcSpan -> DerivInstTys- -> (LHsBinds GhcPs, BagDerivStuff)+ -> (LHsBinds GhcPs, Bag AuxBindSpec) gen_Read_binds get_fixity loc dit@(DerivInstTys{dit_rep_tc = tycon}) = (listToBag [read_prec, default_readlist, default_readlistprec], emptyBag)@@ -1204,7 +1209,7 @@ -} gen_Show_binds :: (Name -> Fixity) -> SrcSpan -> DerivInstTys- -> (LHsBinds GhcPs, BagDerivStuff)+ -> (LHsBinds GhcPs, Bag AuxBindSpec) gen_Show_binds get_fixity loc dit@(DerivInstTys{ dit_rep_tc = tycon , dit_rep_tc_args = tycon_args })@@ -1377,7 +1382,7 @@ gen_Data_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, -- The method bindings- BagDerivStuff) -- Auxiliary bindings+ Bag AuxBindSpec) -- Auxiliary bindings gen_Data_binds loc (DerivInstTys{dit_rep_tc = rep_tc}) = do { -- See Note [Auxiliary binders] dataT_RDR <- new_dataT_rdr_name loc rep_tc@@ -1387,7 +1392,7 @@ , toCon_bind dataC_RDRs, dataTypeOf_bind dataT_RDR ] `unionBags` gcast_binds -- Auxiliary definitions: the data type and constructors- , listToBag $ map DerivAuxBind+ , listToBag ( DerivDataDataType rep_tc dataT_RDR dataC_RDRs : zipWith (\data_con dataC_RDR -> DerivDataConstr data_con dataC_RDR dataT_RDR)@@ -1491,7 +1496,7 @@ dataCast1_RDR, dataCast2_RDR, gcast1_RDR, gcast2_RDR, constr_RDR, dataType_RDR, eqChar_RDR , ltChar_RDR , geChar_RDR , gtChar_RDR , leChar_RDR ,- eqInt_RDR , ltInt_RDR , geInt_RDR , gtInt_RDR , leInt_RDR ,+ eqInt_RDR , ltInt_RDR , geInt_RDR , gtInt_RDR , leInt_RDR , neInt_RDR , eqInt8_RDR , ltInt8_RDR , geInt8_RDR , gtInt8_RDR , leInt8_RDR , eqInt16_RDR , ltInt16_RDR , geInt16_RDR , gtInt16_RDR , leInt16_RDR , eqInt32_RDR , ltInt32_RDR , geInt32_RDR , gtInt32_RDR , leInt32_RDR ,@@ -1531,6 +1536,7 @@ geChar_RDR = varQual_RDR gHC_PRIM (fsLit "geChar#") eqInt_RDR = varQual_RDR gHC_PRIM (fsLit "==#")+neInt_RDR = varQual_RDR gHC_PRIM (fsLit "/=#") ltInt_RDR = varQual_RDR gHC_PRIM (fsLit "<#" ) leInt_RDR = varQual_RDR gHC_PRIM (fsLit "<=#") gtInt_RDR = varQual_RDR gHC_PRIM (fsLit ">#" )@@ -1642,18 +1648,18 @@ -} -gen_Lift_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, BagDerivStuff)+gen_Lift_binds :: SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, Bag AuxBindSpec) gen_Lift_binds loc (DerivInstTys{ dit_rep_tc = tycon , dit_rep_tc_args = tycon_args }) = (listToBag [lift_bind, liftTyped_bind], emptyBag) where lift_bind = mkFunBindEC 1 loc lift_RDR (nlHsApp pure_Expr)- (map (pats_etc mk_exp mk_usplice liftName) data_cons)+ (map (pats_etc mk_untyped_bracket mk_usplice liftName) data_cons) liftTyped_bind = mkFunBindEC 1 loc liftTyped_RDR (nlHsApp unsafeCodeCoerce_Expr . nlHsApp pure_Expr)- (map (pats_etc mk_texp mk_tsplice liftTypedName) data_cons)+ (map (pats_etc mk_typed_bracket mk_tsplice liftTypedName) data_cons) - mk_exp = ExpBr noExtField- mk_texp = TExpBr noExtField+ mk_untyped_bracket = HsUntypedBracket noAnn . ExpBr noExtField+ mk_typed_bracket = HsTypedBracket noAnn mk_usplice = HsUntypedSplice EpAnnNotUsed DollarSplice mk_tsplice = HsTypedSplice EpAnnNotUsed DollarSplice@@ -1666,7 +1672,7 @@ data_con_RDR = getRdrName data_con con_arity = dataConSourceArity data_con as_needed = take con_arity as_RDRs- lift_Expr = noLocA (HsBracket noAnn (mk_bracket br_body))+ lift_Expr = noLocA (mk_bracket br_body) br_body = nlHsApps (Exact (dataConName data_con)) (map lift_var as_needed) @@ -1971,17 +1977,18 @@ -- newtype itself) -> [Type] -- instance head parameters (incl. newtype) -> Type -- the representation type- -> TcM (LHsBinds GhcPs, [LSig GhcPs], BagDerivStuff)+ -> (LHsBinds GhcPs, [LSig GhcPs]) -- See Note [Newtype-deriving instances] gen_Newtype_binds loc' cls inst_tvs inst_tys rhs_ty- = do let ats = classATs cls- (binds, sigs) = mapAndUnzip mk_bind_and_sig (classMethods cls)- atf_insts <- assert (all (not . isDataFamilyTyCon) ats) $- mapM mk_atf_inst ats- return ( listToBag binds- , sigs- , listToBag $ map DerivFamInst atf_insts )+ = (listToBag binds, sigs) where+ (binds, sigs) = mapAndUnzip mk_bind_and_sig (classMethods cls)++ -- Same as inst_tys, but with the last argument type replaced by the+ -- representation type.+ underlying_inst_tys :: [Type]+ underlying_inst_tys = changeLast inst_tys rhs_ty+ locn = noAnnSrcSpan loc' loca = noAnnSrcSpan loc' -- For each class method, generate its derived binding and instance@@ -2051,6 +2058,33 @@ -- Filter out any inferred arguments, since they can't be -- applied with visible type application. +gen_Newtype_fam_insts :: SrcSpan+ -> Class -- the class being derived+ -> [TyVar] -- the tvs in the instance head (this includes+ -- the tvs from both the class types and the+ -- newtype itself)+ -> [Type] -- instance head parameters (incl. newtype)+ -> Type -- the representation type+ -> TcM [FamInst]+-- See Note [GND and associated type families] in GHC.Tc.Deriv+gen_Newtype_fam_insts loc' cls inst_tvs inst_tys rhs_ty+ = assert (all (not . isDataFamilyTyCon) ats) $+ mapM mk_atf_inst ats+ where+ -- Same as inst_tys, but with the last argument type replaced by the+ -- representation type.+ underlying_inst_tys :: [Type]+ underlying_inst_tys = changeLast inst_tys rhs_ty++ ats = classATs cls+ locn = noAnnSrcSpan loc'+ cls_tvs = classTyVars cls+ in_scope = mkInScopeSet $ mkVarSet inst_tvs+ lhs_env = zipTyEnv cls_tvs inst_tys+ lhs_subst = mkTvSubst in_scope lhs_env+ rhs_env = zipTyEnv cls_tvs underlying_inst_tys+ rhs_subst = mkTvSubst in_scope rhs_env+ mk_atf_inst :: TyCon -> TcM FamInst mk_atf_inst fam_tc = do rep_tc_name <- newFamInstTyConName (L locn (tyConName fam_tc))@@ -2061,12 +2095,6 @@ checkValidCoAxBranch fam_tc (coAxiomSingleBranch axiom) newFamInst SynFamilyInst axiom where- cls_tvs = classTyVars cls- in_scope = mkInScopeSet $ mkVarSet inst_tvs- lhs_env = zipTyEnv cls_tvs inst_tys- lhs_subst = mkTvSubst in_scope lhs_env- rhs_env = zipTyEnv cls_tvs underlying_inst_tys- rhs_subst = mkTvSubst in_scope rhs_env fam_tvs = tyConTyVars fam_tc rep_lhs_tys = substTyVars lhs_subst fam_tvs rep_rhs_tys = substTyVars rhs_subst fam_tvs@@ -2076,11 +2104,6 @@ rep_tvs' = scopedSort rep_tvs rep_cvs' = scopedSort rep_cvs - -- Same as inst_tys, but with the last argument type replaced by the- -- representation type.- underlying_inst_tys :: [Type]- underlying_inst_tys = changeLast inst_tys rhs_ty- nlHsAppType :: LHsExpr GhcPs -> Type -> LHsExpr GhcPs nlHsAppType e s = noLocA (HsAppType noSrcSpan e hs_ty) where@@ -2216,25 +2239,13 @@ where mk_sig = mkHsWildCardBndrs . L (noAnnSrcSpan loc) . mkHsImplicitSigType -type SeparateBagsDerivStuff =- -- DerivAuxBinds- ( Bag (LHsBind GhcPs, LSig GhcPs)-- -- Extra family instances (used by DeriveGeneric, DeriveAnyClass, and- -- GeneralizedNewtypeDeriving)- , Bag FamInst )---- | Take a 'BagDerivStuff' and partition it into 'SeparateBagsDerivStuff'.--- Also generate the code for auxiliary bindings based on the declarative--- descriptions in the supplied 'AuxBindSpec's. See @Note [Auxiliary binders]@.-genAuxBinds :: DynFlags -> SrcSpan -> BagDerivStuff -> SeparateBagsDerivStuff-genAuxBinds dflags loc b = (gen_aux_bind_specs b1, b2) where- (b1,b2) = partitionBagWith splitDerivAuxBind b- splitDerivAuxBind (DerivAuxBind x) = Left x- splitDerivAuxBind (DerivFamInst t) = Right t-- gen_aux_bind_specs = snd . foldr gen_aux_bind_spec (emptyOccEnv, emptyBag)-+-- | Take a 'Bag' of 'AuxBindSpec's and generate the code for auxiliary+-- bindings based on the declarative descriptions in the supplied+-- 'AuxBindSpec's. See @Note [Auxiliary binders]@.+genAuxBinds :: DynFlags -> SrcSpan -> Bag AuxBindSpec+ -> Bag (LHsBind GhcPs, LSig GhcPs)+genAuxBinds dflags loc = snd . foldr gen_aux_bind_spec (emptyOccEnv, emptyBag)+ where -- Perform a CSE-like pass over the generated auxiliary bindings to avoid -- code duplication, as described in -- Note [Auxiliary binders] (Wrinkle: Reducing code duplication).@@ -2684,6 +2695,12 @@ -- @dit_cls_tys ++ ['mkTyConApp' dit_tc dit_tc_args]@. Other parts of the -- instance declaration can be found in the 'DerivEnv'. For example, the @Cls@ -- in the example above corresponds to the 'denv_cls' field of 'DerivEnv'.+--+-- Similarly, the type variables that appear in a 'DerivInstTys' value are the+-- same type variables as the 'denv_tvs' in the parent 'DerivEnv'. Accordingly,+-- if we are inferring an instance context, the type variables will be 'TcTyVar'+-- skolems. Otherwise, they will be ordinary 'TyVar's.+-- See @Note [Overlap and deriving]@ in "GHC.Tc.Deriv.Infer". data DerivInstTys = DerivInstTys { dit_cls_tys :: [Type] -- ^ Other arguments to the class except the last@@ -2760,6 +2777,26 @@ cls_tys' = substTys subst cls_tys tc_args' = substTys subst tc_args rep_tc_args' = substTys subst rep_tc_args++-- | Zonk the 'TcTyVar's in a 'DerivInstTys' value to 'TyVar's.+-- See @Note [What is zonking?]@ in "GHC.Tc.Utils.TcMType".+--+-- This is only used in the final zonking step when inferring+-- the context for a derived instance.+-- See @Note [Overlap and deriving]@ in "GHC.Tc.Deriv.Infer".+zonkDerivInstTys :: ZonkEnv -> DerivInstTys -> TcM DerivInstTys+zonkDerivInstTys ze dit@(DerivInstTys { dit_cls_tys = cls_tys+ , dit_tc_args = tc_args+ , dit_rep_tc = rep_tc+ , dit_rep_tc_args = rep_tc_args }) = do+ cls_tys' <- zonkTcTypesToTypesX ze cls_tys+ tc_args' <- zonkTcTypesToTypesX ze tc_args+ rep_tc_args' <- zonkTcTypesToTypesX ze rep_tc_args+ pure dit{ dit_cls_tys = cls_tys'+ , dit_tc_args = tc_args'+ , dit_rep_tc_args = rep_tc_args'+ , dit_dc_inst_arg_env = buildDataConInstArgEnv rep_tc rep_tc_args'+ } {- Note [Auxiliary binders]
compiler/GHC/Tc/Deriv/Generics.hs view
@@ -12,10 +12,11 @@ -- | The deriving code for the Generic class module GHC.Tc.Deriv.Generics- (canDoGenerics+ ( canDoGenerics , canDoGenerics1 , GenericKind(..) , gen_Generic_binds+ , gen_Generic_fam_inst , get_gen1_constrained_tys ) where@@ -76,13 +77,11 @@ \end{itemize} -} -gen_Generic_binds :: GenericKind -> (Name -> Fixity) -> [Type] -> DerivInstTys- -> TcM (LHsBinds GhcPs, [LSig GhcPs], FamInst)-gen_Generic_binds gk get_fixity inst_tys dit = do+gen_Generic_binds :: GenericKind -> SrcSpan -> DerivInstTys+ -> TcM (LHsBinds GhcPs, [LSig GhcPs])+gen_Generic_binds gk loc dit = do dflags <- getDynFlags- repTyInsts <- tc_mkRepFamInsts gk get_fixity inst_tys dit- let (binds, sigs) = mkBindsRep dflags gk dit- return (binds, sigs, repTyInsts)+ return $ mkBindsRep dflags gk loc dit {- ************************************************************************@@ -184,7 +183,7 @@ -- Nor can we do the job if it's an existential data constructor, -- Nor if the args are polymorphic types (I don't think)- bad_arg_type ty = (isUnliftedType ty && not (allowedUnliftedTy ty))+ bad_arg_type ty = (mightBeUnliftedType ty && not (allowedUnliftedTy ty)) || not (isTauTy ty) -- Returns True the Type argument is an unlifted type which has a@@ -310,26 +309,30 @@ -- Generic1 (Gen1). data GenericKind = Gen0 | Gen1 --- as above, but with a payload of the TyCon's name for "the" parameter-data GenericKind_ = Gen0_ | Gen1_ TyVar---- as above, but using a single datacon's name for "the" parameter+-- Like 'GenericKind', but with a payload of a datacon's last universally+-- quantified 'TyVar' in the 'Generic1' case.+--+-- Note that for GADTs, the last TyVar's Name will be different in each data+-- constructor, so it is not correct to simply use the last TyVar in+-- 'tyConTyVars' in 'Gen1_DC'. (See #21185 for an example of what would happen+-- if you tried.) data GenericKind_DC = Gen0_DC | Gen1_DC TyVar -forgetArgVar :: GenericKind_DC -> GenericKind-forgetArgVar Gen0_DC = Gen0-forgetArgVar Gen1_DC{} = Gen1---- When working only within a single datacon, "the" parameter's name should--- match that datacon's name for it.-gk2gkDC :: GenericKind_ -> DataCon -> GenericKind_DC-gk2gkDC Gen0_ _ = Gen0_DC-gk2gkDC Gen1_{} d = Gen1_DC $ last $ dataConUnivTyVars d+-- Construct a 'GenericKind_DC', retrieving the last universally quantified+-- type variable of a 'DataCon' in the 'Generic1' case.+gk2gkDC :: GenericKind -> DataCon -> [Type] -> GenericKind_DC+gk2gkDC Gen0 _ _ = Gen0_DC+gk2gkDC Gen1 dc tc_args = Gen1_DC $ assert (isTyVarTy last_dc_inst_univ)+ $ getTyVar "gk2gkDC" last_dc_inst_univ+ where+ dc_inst_univs = dataConInstUnivs dc tc_args+ last_dc_inst_univ = assert (not (null dc_inst_univs)) $+ last dc_inst_univs -- Bindings for the Generic instance-mkBindsRep :: DynFlags -> GenericKind -> DerivInstTys -> (LHsBinds GhcPs, [LSig GhcPs])-mkBindsRep dflags gk dit@(DerivInstTys{dit_rep_tc = tycon}) = (binds, sigs)+mkBindsRep :: DynFlags -> GenericKind -> SrcSpan -> DerivInstTys -> (LHsBinds GhcPs, [LSig GhcPs])+mkBindsRep dflags gk loc dit@(DerivInstTys{dit_rep_tc = tycon}) = (binds, sigs) where binds = unitBag (mkRdrFunBind (L loc' from01_RDR) [from_eqn]) `unionBags`@@ -365,7 +368,6 @@ from_matches = [mkHsCaseAlt pat rhs | (pat,rhs) <- from_alts] to_matches = [mkHsCaseAlt pat rhs | (pat,rhs) <- to_alts ]- loc = srcLocSpan (getSrcLoc tycon) loc' = noAnnSrcSpan loc loc'' = noAnnSrcSpan loc datacons = tyConDataCons tycon@@ -376,12 +378,7 @@ -- Recurse over the sum first from_alts, to_alts :: [Alt]- (from_alts, to_alts) = mkSum gk_ (1 :: US) dit datacons- where gk_ = case gk of- Gen0 -> Gen0_- Gen1 -> assert (tyvars `lengthAtLeast` 1) $- Gen1_ (last tyvars)- where tyvars = tyConTyVars tycon+ (from_alts, to_alts) = mkSum gk (1 :: US) dit datacons -------------------------------------------------------------------------------- -- The type synonym instance and synonym@@ -389,14 +386,17 @@ -- type Rep_D a b = ...representation type for D ... -------------------------------------------------------------------------------- -tc_mkRepFamInsts :: GenericKind -- Gen0 or Gen1- -> (Name -> Fixity) -- Get the Fixity for a data constructor Name- -> [Type] -- The type(s) to which Generic(1) is applied- -- in the generated instance- -> DerivInstTys -- Information about the last type argument,- -- including the data type's TyCon- -> TcM FamInst -- Generated representation0 coercion-tc_mkRepFamInsts gk get_fixity inst_tys dit@(DerivInstTys{dit_rep_tc = tycon}) =+gen_Generic_fam_inst :: GenericKind -- Gen0 or Gen1+ -> (Name -> Fixity) -- Get the Fixity for a data constructor Name+ -> SrcSpan -- The current source location+ -> DerivInstTys -- Information about the type(s) to which+ -- Generic(1) is applied in the generated+ -- instance, including the data type's TyCon+ -> TcM FamInst -- Generated representation0 coercion+gen_Generic_fam_inst gk get_fixity loc+ dit@(DerivInstTys{ dit_cls_tys = cls_tys+ , dit_tc = tc, dit_tc_args = tc_args+ , dit_rep_tc = tycon }) = -- Consider the example input tycon `D`, where data D a b = D_ a -- Also consider `R:DInt`, where { data family D x y :: * -> * -- ; data instance D Int a b = D_ a }@@ -414,44 +414,28 @@ -- instance Generic1 (Bar x :: k -> *) -- then: -- `arg_k` = k, `inst_ty` = Bar x :: k -> *- (arg_ki, inst_ty) = case (gk, inst_tys) of- (Gen0, [inst_t]) -> (liftedTypeKind, inst_t)- (Gen1, [arg_k, inst_t]) -> (arg_k, inst_t)- _ -> pprPanic "tc_mkRepFamInsts" (ppr inst_tys)-- gk_ = case gk of- Gen0 -> Gen0_- Gen1 -> assert (not $ null all_tyvars)- Gen1_ $ last all_tyvars- where all_tyvars = tyConTyVars tycon+ arg_ki = case (gk, cls_tys) of+ (Gen0, []) -> liftedTypeKind+ (Gen1, [arg_k]) -> arg_k+ _ -> pprPanic "gen_Generic_fam_insts" (ppr cls_tys)+ inst_ty = mkTyConApp tc tc_args+ inst_tys = cls_tys ++ [inst_ty] -- `repTy` = D1 ... (C1 ... (S1 ... (Rec0 a))) :: * -> *- ; repTy <- tc_mkRepTy gk_ get_fixity dit arg_ki+ ; repTy <- tc_mkRepTy gk get_fixity dit arg_ki -- `rep_name` is a name we generate for the synonym ; mod <- getModule- ; loc <- getSrcSpanM ; let tc_occ = nameOccName (tyConName tycon) rep_occ = case gk of Gen0 -> mkGenR tc_occ; Gen1 -> mkGen1R tc_occ ; rep_name <- newGlobalBinder mod rep_occ loc - -- If deriving Generic1, make sure to substitute the last type variable- -- with Any in the generated Rep1 instance. This avoids issues like what- -- is documented in the "wrinkle" section of- -- Note [Generating a correctly typed Rep instance].- ; let env = case gk_ of- Gen0_ -> emptyTvSubstEnv- Gen1_ last_tv- -> zipTyEnv [last_tv] [anyTypeOfKind (tyVarKind last_tv)]- in_scope = mkInScopeSet (tyCoVarsOfTypes inst_tys)- subst = mkTvSubst in_scope env- repTy' = substTyUnchecked subst repTy- tcv' = tyCoVarsOfTypeList inst_ty- (tv', cv') = partition isTyVar tcv'- tvs' = scopedSort tv'- cvs' = scopedSort cv'- axiom = mkSingleCoAxiom Nominal rep_name tvs' [] cvs'- fam_tc inst_tys repTy'+ ; let tcv = tyCoVarsOfTypeList inst_ty+ (tv, cv) = partition isTyVar tcv+ tvs = scopedSort tv+ cvs = scopedSort cv+ axiom = mkSingleCoAxiom Nominal rep_name tvs [] cvs+ fam_tc inst_tys repTy ; newFamInst SynFamilyInst axiom } @@ -524,8 +508,8 @@ else mkComp phi `fmap` go beta -- It must be a composition. -tc_mkRepTy :: -- Gen0_ or Gen1_, for Rep or Rep1- GenericKind_+tc_mkRepTy :: -- Gen0 or Gen1, for Rep or Rep1+ GenericKind -- Get the Fixity for a data constructor Name -> (Name -> Fixity) -- Information about the last type argument to Generic(1)@@ -535,7 +519,8 @@ -> Kind -- Generated representation0 type -> TcM Type-tc_mkRepTy gk_ get_fixity dit@(DerivInstTys{dit_rep_tc = tycon}) k =+tc_mkRepTy gk get_fixity dit@(DerivInstTys{ dit_rep_tc = tycon+ , dit_rep_tc_args = tycon_args }) k = do d1 <- tcLookupTyCon d1TyConName c1 <- tcLookupTyCon c1TyConName@@ -583,7 +568,8 @@ mkD a = mkTyConApp d1 [ k, metaDataTy, sumP (tyConDataCons a) ] mkC a = mkTyConApp c1 [ k , metaConsTy a- , prod (derivDataConInstArgTys a dit)+ , prod (gk2gkDC gk a tycon_args)+ (derivDataConInstArgTys a dit) (dataConSrcBangs a) (dataConImplBangs a) (dataConFieldLabels a)]@@ -592,28 +578,38 @@ -- Sums and products are done in the same way for both Rep and Rep1 sumP l = foldBal mkSum' (mkTyConApp v1 [k]) . map mkC $ l -- The Bool is True if this constructor has labelled fields- prod :: [Type] -> [HsSrcBang] -> [HsImplBang] -> [FieldLabel] -> Type- prod l sb ib fl = foldBal mkProd (mkTyConApp u1 [k])+ prod :: GenericKind_DC -> [Type] -> [HsSrcBang] -> [HsImplBang] -> [FieldLabel] -> Type+ prod gk_ l sb ib fl = foldBal mkProd (mkTyConApp u1 [k]) [ assert (null fl || lengthExceeds fl j) $- arg t sb' ib' (if null fl- then Nothing- else Just (fl !! j))+ arg gk_ t sb' ib' (if null fl+ then Nothing+ else Just (fl !! j)) | (t,sb',ib',j) <- zip4 l sb ib [0..] ] - arg :: Type -> HsSrcBang -> HsImplBang -> Maybe FieldLabel -> Type- arg t (HsSrcBang _ su ss) ib fl = mkS fl su ss ib $ case gk_ of+ arg :: GenericKind_DC -> Type -> HsSrcBang -> HsImplBang -> Maybe FieldLabel -> Type+ arg gk_ t (HsSrcBang _ su ss) ib fl = mkS fl su ss ib $ case gk_ of -- Here we previously used Par0 if t was a type variable, but we -- realized that we can't always guarantee that we are wrapping-up -- all type variables in Par0. So we decided to stop using Par0 -- altogether, and use Rec0 all the time.- Gen0_ -> mkRec0 t- Gen1_ argVar -> argPar argVar t+ Gen0_DC -> mkRec0 t+ Gen1_DC argVar -> argPar argVar t where -- Builds argument representation for Rep1 (more complicated due to -- the presence of composition).- argPar argVar = argTyFold argVar $ ArgTyAlg+ argPar argVar =+ let -- If deriving Generic1, make sure to substitute the last+ -- type variable with Any in the generated Rep1 instance.+ -- This avoids issues like what is documented in the+ -- "wrinkle" section of+ -- Note [Generating a correctly typed Rep instance].+ env = zipTyEnv [argVar] [anyTypeOfKind (tyVarKind argVar)]+ in_scope = mkInScopeSet (tyCoVarsOfTypes tycon_args)+ subst = mkTvSubst in_scope env in++ substTy subst . argTyFold argVar (ArgTyAlg {ata_rec0 = mkRec0, ata_par1 = mkPar1,- ata_rec1 = mkRec1, ata_comp = mkComp comp k}+ ata_rec1 = mkRec1, ata_comp = mkComp comp k}) tyConName_user = case tyConFamInst_maybe tycon of Just (ptycon, _) -> tyConName ptycon@@ -713,7 +709,7 @@ -- Dealing with sums -------------------------------------------------------------------------------- -mkSum :: GenericKind_ -- Generic or Generic1?+mkSum :: GenericKind -- Generic or Generic1? -> US -- Base for generating unique names -> DerivInstTys -- Information about the last type argument to Generic(1) -> [DataCon] -- The data constructors@@ -728,23 +724,24 @@ -- These M1s are meta-information for the datatype -- Datatype with at least one constructor-mkSum gk_ us dit datacons =+mkSum gk us dit datacons = -- switch the payload of gk_ to be datacon-centric instead of tycon-centric- unzip [ mk1Sum (gk2gkDC gk_ d) us i (length datacons) dit d+ unzip [ mk1Sum gk us i (length datacons) dit d | (d,i) <- zip datacons [1..] ] -- Build the sum for a particular constructor-mk1Sum :: GenericKind_DC -- Generic or Generic1?- -> US -- Base for generating unique names- -> Int -- The index of this constructor- -> Int -- Total number of constructors- -> DerivInstTys -- Information about the last type argument to Generic(1)- -> DataCon -- The data constructor- -> (Alt, -- Alternative for the T->Trep "from" function- Alt) -- Alternative for the Trep->T "to" function-mk1Sum gk_ us i n dit datacon = (from_alt, to_alt)+mk1Sum :: GenericKind -- Generic or Generic1?+ -> US -- Base for generating unique names+ -> Int -- The index of this constructor+ -> Int -- Total number of constructors+ -> DerivInstTys -- Information about the last type argument to Generic(1)+ -> DataCon -- The data constructor+ -> (Alt, -- Alternative for the T->Trep "from" function+ Alt) -- Alternative for the Trep->T "to" function+mk1Sum gk us i n dit@(DerivInstTys{dit_rep_tc_args = tc_args}) datacon+ = (from_alt, to_alt) where- gk = forgetArgVar gk_+ gk_ = gk2gkDC gk datacon tc_args -- Existentials already excluded argTys = derivDataConInstArgTys datacon dit
compiler/GHC/Tc/Deriv/Infer.hs view
@@ -21,7 +21,6 @@ import GHC.Core.Class import GHC.Core.DataCon import GHC.Utils.Error-import GHC.Tc.Utils.Instantiate import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Utils.Panic.Plain@@ -44,7 +43,7 @@ import GHC.Tc.Solver import GHC.Tc.Solver.Monad ( runTcS ) import GHC.Tc.Validity (validDerivPred)-import GHC.Tc.Utils.Unify (buildImplicationFor, checkConstraints)+import GHC.Tc.Utils.Unify (buildImplicationFor) import GHC.Builtin.Types (typeToTypeKind) import GHC.Core.Unify (tcUnifyTy) import GHC.Utils.Misc@@ -60,7 +59,7 @@ ---------------------- inferConstraints :: DerivSpecMechanism- -> DerivM ([ThetaOrigin], [TyVar], [TcType], DerivSpecMechanism)+ -> DerivM (ThetaSpec, [TyVar], [TcType], DerivSpecMechanism) -- inferConstraints figures out the constraints needed for the -- instance declaration generated by a 'deriving' clause on a -- data type declaration. It also returns the new in-scope type@@ -81,7 +80,7 @@ , denv_cls = main_cls , denv_inst_tys = inst_tys } <- ask ; wildcard <- isStandaloneWildcardDeriv- ; let infer_constraints :: DerivM ([ThetaOrigin], [TyVar], [TcType], DerivSpecMechanism)+ ; let infer_constraints :: DerivM (ThetaSpec, [TyVar], [TcType], DerivSpecMechanism) infer_constraints = case mechanism of DerivSpecStock{dsm_stock_dit = dit}@@ -106,8 +105,8 @@ -- this rule is stock deriving. See -- Note [Inferring the instance context]. infer_constraints_simple- :: DerivM [ThetaOrigin]- -> DerivM ([ThetaOrigin], [TyVar], [TcType], DerivSpecMechanism)+ :: DerivM ThetaSpec+ -> DerivM (ThetaSpec, [TyVar], [TcType], DerivSpecMechanism) infer_constraints_simple infer_thetas = do thetas <- infer_thetas pure (thetas, tvs, inst_tys, mechanism)@@ -116,10 +115,10 @@ -- See Note [Superclasses of derived instance] cls_tvs = classTyVars main_cls sc_constraints = assertPpr (equalLength cls_tvs inst_tys)- (ppr main_cls <+> ppr inst_tys)- [ mkThetaOrigin (mkDerivOrigin wildcard)- TypeLevel [] [] [] $- substTheta cls_subst (classSCTheta main_cls) ]+ (ppr main_cls <+> ppr inst_tys) $+ mkDirectThetaSpec+ (mkDerivOrigin wildcard) TypeLevel+ (substTheta cls_subst (classSCTheta main_cls)) cls_subst = assert (equalLength cls_tvs inst_tys) $ zipTvSubst cls_tvs inst_tys @@ -138,7 +137,7 @@ -- -- > data Foo = MkFoo Int Char deriving Show ----- We would infer the following constraints ('ThetaOrigin's):+-- We would infer the following constraints ('ThetaSpec's): -- -- > (Show Int, Show Char) --@@ -156,7 +155,7 @@ -- 'TyVar's/'TcType's, /not/ @[k]@/@[k, f, g]@. -- See Note [Inferring the instance context]. inferConstraintsStock :: DerivInstTys- -> DerivM ([ThetaOrigin], [TyVar], [TcType], DerivInstTys)+ -> DerivM (ThetaSpec, [TyVar], [TcType], DerivInstTys) inferConstraintsStock dit@(DerivInstTys { dit_cls_tys = cls_tys , dit_tc = tc , dit_tc_args = tc_args@@ -179,8 +178,8 @@ con_arg_constraints :: (CtOrigin -> TypeOrKind -> Type- -> [([PredOrigin], Maybe TCvSubst)])- -> ([ThetaOrigin], [TyVar], [TcType], DerivInstTys)+ -> [(ThetaSpec, Maybe TCvSubst)])+ -> (ThetaSpec, [TyVar], [TcType], DerivInstTys) con_arg_constraints get_arg_constraints = let -- Constraints from the fields of each data constructor. (predss, mbSubsts) = unzip@@ -220,13 +219,14 @@ unmapped_tvs = filter (\v -> v `notElemTCvSubst` subst && not (v `isInScope` subst)) tvs (subst', _) = substTyVarBndrs subst unmapped_tvs- stupid_theta_origin = mkThetaOrigin deriv_origin TypeLevel [] [] [] $- substTheta subst' stupid_theta- preds' = map (substPredOrigin subst') preds+ stupid_theta_origin = mkDirectThetaSpec+ deriv_origin TypeLevel+ (substTheta subst' stupid_theta)+ preds' = map (substPredSpec subst') preds inst_tys' = substTys subst' inst_tys dit' = substDerivInstTys subst' dit tvs' = tyCoVarsOfTypesWellScoped inst_tys'- in ( [stupid_theta_origin, mkThetaOriginFromPreds preds']+ in ( stupid_theta_origin ++ preds' , tvs', inst_tys', dit' ) is_generic = main_cls `hasKey` genClassKey@@ -236,13 +236,13 @@ || is_generic1 get_gen1_constraints :: Class -> CtOrigin -> TypeOrKind -> Type- -> [([PredOrigin], Maybe TCvSubst)]+ -> [(ThetaSpec, Maybe TCvSubst)] get_gen1_constraints functor_cls orig t_or_k ty = mk_functor_like_constraints orig t_or_k functor_cls $ get_gen1_constrained_tys last_tv ty get_std_constrained_tys :: CtOrigin -> TypeOrKind -> Type- -> [([PredOrigin], Maybe TCvSubst)]+ -> [(ThetaSpec, Maybe TCvSubst)] get_std_constrained_tys orig t_or_k ty | is_functor_like = mk_functor_like_constraints orig t_or_k main_cls $@@ -253,7 +253,7 @@ mk_functor_like_constraints :: CtOrigin -> TypeOrKind -> Class -> [Type]- -> [([PredOrigin], Maybe TCvSubst)]+ -> [(ThetaSpec, Maybe TCvSubst)] -- 'cls' is usually main_cls (Functor or Traversable etc), but if -- main_cls = Generic1, then 'cls' can be Functor; see -- get_gen1_constraints@@ -268,8 +268,12 @@ mk_functor_like_constraints orig t_or_k cls = map $ \ty -> let ki = tcTypeKind ty in ( [ mk_cls_pred orig t_or_k cls ty- , mkPredOrigin orig KindLevel- (mkPrimEqPred ki typeToTypeKind) ]+ , SimplePredSpec+ { sps_pred = mkPrimEqPred ki typeToTypeKind+ , sps_origin = orig+ , sps_type_or_kind = KindLevel+ }+ ] , tcUnifyTy ki typeToTypeKind ) @@ -284,9 +288,7 @@ -- Reason: when the IF holds, we generate a method -- dataCast2 f = gcast2 f -- and we need the Data constraints to typecheck the method- extra_constraints = [mkThetaOriginFromPreds constrs]- where- constrs+ extra_constraints | main_cls `hasKey` dataClassKey , all (isLiftedTypeKind . tcTypeKind) rep_tc_args = [ mk_cls_pred deriv_origin t_or_k main_cls ty@@ -296,7 +298,11 @@ mk_cls_pred orig t_or_k cls ty -- Don't forget to apply to cls_tys' too- = mkPredOrigin orig t_or_k (mkClassPred cls (cls_tys' ++ [ty]))+ = SimplePredSpec+ { sps_pred = mkClassPred cls (cls_tys' ++ [ty])+ , sps_origin = orig+ , sps_type_or_kind = t_or_k+ } cls_tys' | is_generic1 = [] -- In the awkward Generic1 case, cls_tys' should be -- empty, since we are applying the class Functor.@@ -337,36 +343,32 @@ -- See Note [Gathering and simplifying constraints for DeriveAnyClass] -- for an explanation of how these constraints are used to determine the -- derived instance context.-inferConstraintsAnyclass :: DerivM [ThetaOrigin]+inferConstraintsAnyclass :: DerivM ThetaSpec inferConstraintsAnyclass- = do { DerivEnv { denv_cls = cls- , denv_inst_tys = inst_tys } <- ask- ; wildcard <- isStandaloneWildcardDeriv-+ = do { DerivEnv { denv_cls = cls+ , denv_inst_tys = inst_tys } <- ask ; let gen_dms = [ (sel_id, dm_ty) | (sel_id, Just (_, GenericDM dm_ty)) <- classOpItems cls ]-- cls_tvs = classTyVars cls+ ; wildcard <- isStandaloneWildcardDeriv - do_one_meth :: (Id, Type) -> TcM ThetaOrigin+ ; let meth_pred :: (Id, Type) -> PredSpec -- (Id,Type) are the selector Id and the generic default method type -- NB: the latter is /not/ quantified over the class variables -- See Note [Gathering and simplifying constraints for DeriveAnyClass]- do_one_meth (sel_id, gen_dm_ty)- = do { let (sel_tvs, _cls_pred, meth_ty)- = tcSplitMethodTy (varType sel_id)- meth_ty' = substTyWith sel_tvs inst_tys meth_ty- (meth_tvs, meth_theta, meth_tau)- = tcSplitNestedSigmaTys meth_ty'-- gen_dm_ty' = substTyWith cls_tvs inst_tys gen_dm_ty- (dm_tvs, dm_theta, dm_tau)- = tcSplitNestedSigmaTys gen_dm_ty'- tau_eq = mkPrimEqPred meth_tau dm_tau- ; return (mkThetaOrigin (mkDerivOrigin wildcard) TypeLevel- meth_tvs dm_tvs meth_theta (tau_eq:dm_theta)) }+ meth_pred (sel_id, gen_dm_ty)+ = let (sel_tvs, _cls_pred, meth_ty) = tcSplitMethodTy (varType sel_id)+ meth_ty' = substTyWith sel_tvs inst_tys meth_ty+ gen_dm_ty' = substTyWith sel_tvs inst_tys gen_dm_ty in+ -- This is the only place where a SubTypePredSpec is+ -- constructed instead of a SimplePredSpec. See+ -- Note [Gathering and simplifying constraints for DeriveAnyClass]+ -- for a more in-depth explanation.+ SubTypePredSpec { stps_ty_actual = gen_dm_ty'+ , stps_ty_expected = meth_ty'+ , stps_origin = mkDerivOrigin wildcard+ } - ; lift $ mapM do_one_meth gen_dms }+ ; pure $ map meth_pred gen_dms } -- Like 'inferConstraints', but used only for @GeneralizedNewtypeDeriving@ and -- @DerivingVia@. Since both strategies generate code involving 'coerce', the@@ -375,11 +377,11 @@ -- -- > newtype Age = MkAge Int deriving newtype Num ----- We would infer the following constraints ('ThetaOrigin's):+-- We would infer the following constraints ('ThetaSpec'): -- -- > (Num Int, Coercible Age Int) inferConstraintsCoerceBased :: [Type] -> Type- -> DerivM [ThetaOrigin]+ -> DerivM ThetaSpec inferConstraintsCoerceBased cls_tys rep_ty = do DerivEnv { denv_tvs = tvs , denv_cls = cls@@ -391,7 +393,10 @@ -- (for DerivingVia). rep_tys ty = cls_tys ++ [ty] rep_pred ty = mkClassPred cls (rep_tys ty)- rep_pred_o ty = mkPredOrigin deriv_origin TypeLevel (rep_pred ty)+ rep_pred_o ty = SimplePredSpec { sps_pred = rep_pred ty+ , sps_origin = deriv_origin+ , sps_type_or_kind = TypeLevel+ } -- rep_pred is the representation dictionary, from where -- we are going to get all the methods for the final -- dictionary@@ -401,23 +406,23 @@ -- If there are no methods, we don't need any constraints -- Otherwise we need (C rep_ty), for the representation methods, -- and constraints to coerce each individual method- meth_preds :: Type -> [PredOrigin]+ meth_preds :: Type -> ThetaSpec meth_preds ty | null meths = [] -- No methods => no constraints -- (#12814) | otherwise = rep_pred_o ty : coercible_constraints ty meths = classMethods cls coercible_constraints ty- = [ mkPredOrigin (DerivOriginCoerce meth t1 t2 sa_wildcard)- TypeLevel (mkReprPrimEqPred t1 t2)+ = [ SimplePredSpec+ { sps_pred = mkReprPrimEqPred t1 t2+ , sps_origin = DerivOriginCoerce meth t1 t2 sa_wildcard+ , sps_type_or_kind = TypeLevel+ } | meth <- meths , let (Pair t1 t2) = mkCoerceClassMethEqn cls tvs inst_tys ty meth ] - all_thetas :: Type -> [ThetaOrigin]- all_thetas ty = [mkThetaOriginFromPreds $ meth_preds ty]-- pure (all_thetas rep_ty)+ pure (meth_preds rep_ty) {- Note [Inferring the instance context] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -631,7 +636,7 @@ -} -simplifyInstanceContexts :: [DerivSpec [ThetaOrigin]]+simplifyInstanceContexts :: [DerivSpec ThetaSpec] -> TcM [DerivSpec ThetaType] -- Used only for deriving clauses or standalone deriving with an -- extra-constraints wildcard (InferContext)@@ -641,7 +646,10 @@ simplifyInstanceContexts infer_specs = do { traceTc "simplifyInstanceContexts" $ vcat (map pprDerivSpec infer_specs)- ; iterate_deriv 1 initial_solutions }+ ; final_specs <- iterate_deriv 1 initial_solutions+ -- After simplification finishes, zonk the TcTyVars as described+ -- in Note [Overlap and deriving].+ ; traverse zonkDerivSpec final_specs } where ------------------------------------------------------------------ -- The initial solutions for the equations claim that each@@ -665,13 +673,14 @@ | otherwise = do { -- Extend the inst info from the explicit instance decls -- with the current set of solutions, and simplify each RHS- inst_specs <- zipWithM newDerivClsInst current_solns infer_specs+ inst_specs <- zipWithM (\soln -> newDerivClsInst . setDerivSpecTheta soln)+ current_solns infer_specs ; new_solns <- checkNoErrs $ extendLocalInstEnv inst_specs $ mapM gen_soln infer_specs ; if (current_solns `eqSolution` new_solns) then- return [ spec { ds_theta = soln }+ return [ setDerivSpecTheta soln spec | (spec, soln) <- zip infer_specs current_solns ] else iterate_deriv (n+1) new_solns }@@ -681,12 +690,13 @@ -- See Note [Deterministic simplifyInstanceContexts] canSolution = map (sortBy nonDetCmpType) ------------------------------------------------------------------- gen_soln :: DerivSpec [ThetaOrigin] -> TcM ThetaType+ gen_soln :: DerivSpec ThetaSpec -> TcM ThetaType gen_soln (DS { ds_loc = loc, ds_tvs = tyvars- , ds_cls = clas, ds_tys = inst_tys, ds_theta = deriv_rhs })+ , ds_cls = clas, ds_tys = inst_tys, ds_theta = deriv_rhs+ , ds_skol_info = skol_info, ds_user_ctxt = user_ctxt }) = setSrcSpan loc $ addErrCtxt (derivInstCtxt the_pred) $- do { theta <- simplifyDeriv the_pred tyvars deriv_rhs+ do { theta <- simplifyDeriv skol_info user_ctxt tyvars deriv_rhs -- checkValidInstance tyvars theta clas inst_tys -- Not necessary; see Note [Exotic derived instance contexts] @@ -712,78 +722,27 @@ -- | Given @instance (wanted) => C inst_ty@, simplify 'wanted' as much -- as possible. Fail if not possible.-simplifyDeriv :: PredType -- ^ @C inst_ty@, head of the instance we are- -- deriving. Only used for SkolemInfo.- -> [TyVar] -- ^ The tyvars bound by @inst_ty@.- -> [ThetaOrigin] -- ^ Given and wanted constraints+simplifyDeriv :: SkolemInfo -- ^ The 'SkolemInfo' used to skolemise the+ -- 'TcTyVar' arguments+ -> UserTypeCtxt -- ^ Used to inform error messages as to whether+ -- we are in a @deriving@ clause or a standalone+ -- @deriving@ declaration+ -> [TcTyVar] -- ^ The tyvars bound by @inst_ty@.+ -> ThetaSpec -- ^ The constraints to solve and simplify -> TcM ThetaType -- ^ Needed constraints (after simplification), -- i.e. @['PredType']@.-simplifyDeriv pred tvs thetas- = do { skol_info <- mkSkolemInfo (DerivSkol pred)- ; (skol_subst, tvs_skols) <- tcInstSkolTyVars skol_info tvs -- Skolemize- -- The constraint solving machinery- -- expects *TcTyVars* not TyVars.- -- We use *non-overlappable* (vanilla) skolems- -- See Note [Overlap and deriving]-- ; let skol_set = mkVarSet tvs_skols- doc = text "deriving" <+> parens (ppr pred)-- mk_given_ev :: PredType -> TcM EvVar- mk_given_ev given =- let given_pred = substTy skol_subst given- in newEvVar given_pred-- emit_wanted_constraints :: [TyVar] -> [PredOrigin] -> TcM ()- emit_wanted_constraints metas_to_be preds- = do { -- We instantiate metas_to_be with fresh meta type- -- variables. Currently, these can only be type variables- -- quantified in generic default type signatures.- -- See Note [Gathering and simplifying constraints for- -- DeriveAnyClass]- (meta_subst, _meta_tvs) <- newMetaTyVars metas_to_be-- -- Now make a constraint for each of the instantiated predicates- ; let wanted_subst = skol_subst `unionTCvSubst` meta_subst- mk_wanted_ct (PredOrigin wanted orig t_or_k)- = do { ev <- newWanted orig (Just t_or_k) $- substTyUnchecked wanted_subst wanted- ; return (mkNonCanonical ev) }- ; cts <- mapM mk_wanted_ct preds-- -- And emit them into the monad- ; emitSimples (listToCts cts) }-- -- Create the implications we need to solve. For stock and newtype- -- deriving, these implication constraints will be simple class- -- constraints like (C a, Ord b).- -- But with DeriveAnyClass, we make an implication constraint.- -- See Note [Gathering and simplifying constraints for DeriveAnyClass]- mk_wanteds :: ThetaOrigin -> TcM WantedConstraints- mk_wanteds (ThetaOrigin { to_anyclass_skols = ac_skols- , to_anyclass_metas = ac_metas- , to_anyclass_givens = ac_givens- , to_wanted_origins = preds })- = do { ac_given_evs <- mapM mk_given_ev ac_givens- ; (_, wanteds)- <- captureConstraints $- checkConstraints (getSkolemInfo skol_info) ac_skols ac_given_evs $- -- The checkConstraints bumps the TcLevel, and- -- wraps the wanted constraints in an implication,- -- when (but only when) necessary- emit_wanted_constraints ac_metas preds- ; pure wanteds }+simplifyDeriv skol_info user_ctxt tvs theta+ = do { let skol_set = mkVarSet tvs -- See [STEP DAC BUILD] -- Generate the implication constraints, one for each method, to solve -- with the skolemized variables. Start "one level down" because- -- we are going to wrap the result in an implication with tvs_skols,+ -- we are going to wrap the result in an implication with tvs, -- in step [DAC RESIDUAL]- ; (tc_lvl, wanteds) <- pushTcLevelM $- mapM mk_wanteds thetas+ ; (tc_lvl, wanteds) <- captureThetaSpecConstraints user_ctxt theta ; traceTc "simplifyDeriv inputs" $- vcat [ pprTyVars tvs $$ ppr thetas $$ ppr wanteds, doc ]+ vcat [ pprTyVars tvs $$ ppr theta $$ ppr wanteds, ppr skol_info ] -- See [STEP DAC SOLVE] -- Simplify the constraints, starting at the same level at which@@ -791,8 +750,7 @@ -- simplifyInfer) ; (solved_wanteds, _) <- setTcLevel tc_lvl $ runTcS $- solveWanteds $- unionsWC wanteds+ solveWanteds wanteds -- It's not yet zonked! Obviously zonk it before peering at it ; solved_wanteds <- zonkWC solved_wanteds@@ -816,7 +774,7 @@ where p = ctPred ct ; traceTc "simplifyDeriv outputs" $- vcat [ ppr tvs_skols, ppr residual_simple, ppr good ]+ vcat [ ppr tvs, ppr residual_simple, ppr good ] -- Return the good unsolved constraints (unskolemizing on the way out.) ; let min_theta = mkMinimalBySCs id (bagToList good)@@ -826,8 +784,6 @@ -- constraints. -- See Note [Gathering and simplifying constraints for -- DeriveAnyClass]- subst_skol = zipTvSubst tvs_skols $ mkTyVarTys tvs- -- The reverse substitution (sigh) -- See [STEP DAC RESIDUAL] -- Ensure that min_theta is enough to solve /all/ the constraints in@@ -836,7 +792,7 @@ -- forall tvs. min_theta => solved_wanteds ; min_theta_vars <- mapM newEvVar min_theta ; (leftover_implic, _)- <- buildImplicationFor tc_lvl (getSkolemInfo skol_info) tvs_skols+ <- buildImplicationFor tc_lvl (getSkolemInfo skol_info) tvs min_theta_vars solved_wanteds -- This call to simplifyTop is purely for error reporting -- See Note [Error reporting for deriving clauses]@@ -844,7 +800,7 @@ -- in this line of code. ; simplifyTopImplic leftover_implic - ; return (substTheta subst_skol min_theta) }+ ; return min_theta } {- Note [Overlap and deriving]@@ -868,10 +824,21 @@ and we want to infer f :: Show [a] => a -> String -BOTTOM LINE: use vanilla, non-overlappable skolems when inferring- the context for the derived instance.- Hence tcInstSkolTyVars not tcInstSuperSkolTyVars+As a result, we use vanilla, non-overlappable skolems when inferring the+context for the derived instances. Hence, we instantiate the type variables+using tcInstSkolTyVars, not tcInstSuperSkolTyVars. +We do this skolemisation in GHC.Tc.Deriv.mkEqnHelp, a function which occurs+very early in the deriving pipeline, so that by the time GHC needs to infer the+instance context, all of the types in the computed DerivSpec have been+skolemised appropriately. After the instance context inference has completed,+GHC zonks the TcTyVars in the DerivSpec to ensure that types like+a[sk:1] do not appear in -ddump-deriv output.++All of this is only needed when inferring an instance context, i.e., the+InferContext case. For the SupplyContext case, we don't bother skolemising+at all.+ Note [Gathering and simplifying constraints for DeriveAnyClass] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DeriveAnyClass works quite differently from stock and newtype deriving in@@ -901,7 +868,7 @@ $gdm_bar x y = show x ++ show (range (y,y)) (and similarly for baz). Now consider a 'deriving' clause- data Maybe s = ... deriving Foo+ data Maybe s = ... deriving anyclass Foo This derives an instance of the form: instance (CX) => Foo (Maybe s) where@@ -910,15 +877,35 @@ Now it is GHC's job to fill in a suitable instance context (CX). If GHC were typechecking the binding- bar = $gdm bar+ bar = $gdm_bar it would * skolemise the expected type of bar * instantiate the type of $gdm_bar with meta-type variables * build an implication constraint [STEP DAC BUILD]-So that's what we do. We build the constraint (call it C1)+So that's what we do. Fortunately, there is already functionality within GHC+to that does all of the above—namely, tcSubTypeSigma. In the example above,+we want to use tcSubTypeSigma to check the following subtyping relation: + forall c. (Show a, Ix c) => Maybe s -> c -> String -- actual type+ <= forall b. (Ix b) => Maybe s -> b -> String -- expected type++That is, we check that the type of $gdm_bar (the actual type) is more+polymorphic than the type of bar (the expected type). We use SubTypePredSpec,+a special form of PredSpec that is only used by DeriveAnyClass, to store+the actual and expected types.++(Aside: having a separate SubTypePredSpec is not strictly necessary, as we+could theoretically construct this implication constraint by hand and store it+in a SimplePredSpec. In fact, GHC used to do this. However, this is easier+said than done, and there were numerous subtle bugs that resulted from getting+this step wrong, such as #20719. Ultimately, we decided that special-casing a+PredSpec specifically for DeriveAnyClass was worth it.)++tcSubTypeSigma will ultimately spit out an implication constraint, which will+look something like this (call it C1):+ forall[2] b. Ix b => (Show (Maybe s), Ix cc, Maybe s -> b -> String ~ Maybe s -> cc -> String)@@ -928,15 +915,32 @@ going to wrap it in a forall[1] in [STEP DAC RESIDUAL] * The 'b' comes from the quantified type variable in the expected type- of bar (i.e., 'to_anyclass_skols' in 'ThetaOrigin'). The 'cc' is a unification- variable that comes from instantiating the quantified type variable 'c' in- $gdm_bar's type (i.e., 'to_anyclass_metas' in 'ThetaOrigin).+ of bar. The 'cc' is a unification variable that comes from instantiating the+ quantified type variable 'c' in $gdm_bar's type. The finer details of+ skolemisation and metavariable instantiation are handled behind the scenes+ by tcSubTypeSigma. -* The (Ix b) constraint comes from the context of bar's type- (i.e., 'to_wanted_givens' in 'ThetaOrigin'). The (Show (Maybe s)) and (Ix cc)- constraints come from the context of $gdm_bar's type- (i.e., 'to_anyclass_givens' in 'ThetaOrigin').+* It is important that `b` be distinct from `cc`. In this example, this is+ clearly the case, but it is not always so obvious when the type variables are+ hidden behind type synonyms. Suppose the example were written like this,+ for example: + type Method a = forall b. Ix b => a -> b -> String+ class Foo a where+ bar :: Method a+ default bar :: Show a => Method a+ bar = ...++ Both method signatures quantify a `b` once the `Method` type synonym is+ expanded. To ensure that GHC doesn't confuse the two `b`s during+ typechecking, tcSubTypeSigma instantiates the `b` in the original signature+ with a fresh skolem and the `b` in the default signature with a fresh+ unification variable. Doing so prevents #20719 from happening.++* The (Ix b) constraint comes from the context of bar's type. The+ (Show (Maybe s)) and (Ix cc) constraints come from the context of $gdm_bar's+ type.+ * The equality constraint (Maybe s -> b -> String) ~ (Maybe s -> cc -> String) comes from marrying up the instantiated type of $gdm_bar with the specified type of bar. Notice that the type variables from the instance, 's' in this@@ -947,7 +951,7 @@ unification variable across multiple iterations, then bad things can happen, such as #14933. -Similarly for 'baz', giving the constraint C2+Similarly for 'baz', tcSubTypeSigma gives the constraint C2 forall[2]. Eq (Maybe s) => (Ord a, Show a, Maybe s -> Maybe s -> Bool
compiler/GHC/Tc/Deriv/Utils.hs view
@@ -10,13 +10,15 @@ -- | Error-checking and other utilities for @deriving@ clauses or declarations. module GHC.Tc.Deriv.Utils ( DerivM, DerivEnv(..),- DerivSpec(..), pprDerivSpec,+ DerivSpec(..), pprDerivSpec, setDerivSpecTheta, zonkDerivSpec, DerivSpecMechanism(..), derivSpecMechanismToStrategy, isDerivSpecStock,- isDerivSpecNewtype, isDerivSpecAnyClass, isDerivSpecVia,- DerivContext(..), OriginativeDerivStatus(..),- isStandaloneDeriv, isStandaloneWildcardDeriv, mkDerivOrigin,- PredOrigin(..), ThetaOrigin(..), mkPredOrigin,- mkThetaOrigin, mkThetaOriginFromPreds, substPredOrigin,+ isDerivSpecNewtype, isDerivSpecAnyClass,+ isDerivSpecVia, zonkDerivSpecMechanism,+ DerivContext(..), OriginativeDerivStatus(..), StockGenFns(..),+ isStandaloneDeriv, isStandaloneWildcardDeriv,+ askDerivUserTypeCtxt, mkDerivOrigin,+ PredSpec(..), ThetaSpec,+ mkDirectThetaSpec, substPredSpec, captureThetaSpecConstraints, checkOriginativeSideConditions, hasStockDeriving, std_class_via_coercible, non_coercible_class, newDerivClsInst, extendLocalInstEnv@@ -28,6 +30,7 @@ import GHC.Types.Basic import GHC.Core.Class import GHC.Core.DataCon+import GHC.Core.FamInstEnv import GHC.Driver.Session import GHC.Utils.Error import GHC.Types.Fixity.Env (lookupFixity)@@ -46,9 +49,12 @@ import GHC.Tc.Deriv.Functor import GHC.Tc.Deriv.Generics import GHC.Tc.Errors.Types+import GHC.Tc.Types.Constraint (WantedConstraints, mkNonCanonical) import GHC.Tc.Types.Origin import GHC.Tc.Utils.Monad import GHC.Tc.Utils.TcType+import GHC.Tc.Utils.Unify (tcSubTypeSigma)+import GHC.Tc.Utils.Zonk import GHC.Builtin.Names.TH (liftClassKey) import GHC.Core.TyCon import GHC.Core.Type@@ -56,6 +62,7 @@ import GHC.Types.Var.Set import Control.Monad.Trans.Reader+import Data.Foldable (traverse_) import Data.Maybe import qualified GHC.LanguageExtensions as LangExt import GHC.Data.List.SetOps (assocMaybe)@@ -83,6 +90,16 @@ go (InferContext wildcard) = isJust wildcard go (SupplyContext {}) = False +-- | Return 'InstDeclCtxt' if processing with a standalone @deriving@+-- declaration or 'DerivClauseCtxt' if processing a @deriving@ clause.+askDerivUserTypeCtxt :: DerivM UserTypeCtxt+askDerivUserTypeCtxt = asks (go . denv_ctxt)+ where+ go :: DerivContext -> UserTypeCtxt+ go (SupplyContext {}) = InstDeclCtxt True+ go (InferContext Just{}) = InstDeclCtxt True+ go (InferContext Nothing) = DerivClauseCtxt+ -- | @'mkDerivOrigin' wc@ returns 'StandAloneDerivOrigin' if @wc@ is 'True', -- and 'DerivClauseOrigin' if @wc@ is 'False'. Useful for error-reporting. mkDerivOrigin :: Bool -> CtOrigin@@ -97,7 +114,13 @@ { denv_overlap_mode :: Maybe OverlapMode -- ^ Is this an overlapping instance? , denv_tvs :: [TyVar]- -- ^ Universally quantified type variables in the instance+ -- ^ Universally quantified type variables in the instance. If the+ -- @denv_ctxt@ is 'InferContext', these will be 'TcTyVar' skolems.+ -- If the @denv_ctxt@ is 'SupplyContext', these will be ordinary 'TyVar's.+ -- See @Note [Overlap and deriving]@ in "GHC.Tc.Deriv.Infer".+ --+ -- All type variables that appear in the 'denv_inst_tys', 'denv_ctxt',+ -- 'denv_skol_info', and 'denv_strat' should come from 'denv_tvs'. , denv_cls :: Class -- ^ Class for which we need to derive an instance , denv_inst_tys :: [Type]@@ -108,6 +131,9 @@ -- 'InferContext' for @deriving@ clauses, or for standalone deriving that -- uses a wildcard constraint. -- See @Note [Inferring the instance context]@.+ , denv_skol_info :: SkolemInfo+ -- ^ The 'SkolemInfo' used to skolemise the @denv_tvs@ in the case where+ -- the 'denv_ctxt' is 'InferContext'. , denv_strat :: Maybe (DerivStrategy GhcTc) -- ^ 'Just' if user requests a particular deriving strategy. -- Otherwise, 'Nothing'.@@ -119,6 +145,7 @@ , denv_cls = cls , denv_inst_tys = inst_tys , denv_ctxt = ctxt+ , denv_skol_info = skol_info , denv_strat = mb_strat }) = hang (text "DerivEnv") 2 (vcat [ text "denv_overlap_mode" <+> ppr overlap_mode@@ -126,6 +153,7 @@ , text "denv_cls" <+> ppr cls , text "denv_inst_tys" <+> ppr inst_tys , text "denv_ctxt" <+> ppr ctxt+ , text "denv_skol_info" <+> ppr skol_info , text "denv_strat" <+> ppr mb_strat ]) data DerivSpec theta = DS { ds_loc :: SrcSpan@@ -134,6 +162,8 @@ , ds_theta :: theta , ds_cls :: Class , ds_tys :: [Type]+ , ds_skol_info :: SkolemInfo+ , ds_user_ctxt :: UserTypeCtxt , ds_overlap :: Maybe OverlapMode , ds_standalone_wildcard :: Maybe SrcSpan -- See Note [Inferring the instance context]@@ -142,11 +172,20 @@ -- This spec implies a dfun declaration of the form -- df :: forall tvs. theta => C tys -- The Name is the name for the DFun we'll build- -- The tyvars bind all the variables in the theta+ -- The tyvars bind all the variables in the rest of the DerivSpec.+ -- If we are inferring an instance context, the tyvars will be TcTyVar+ -- skolems. After the instance context inference is over, the tyvars+ -- will be zonked to TyVars. See+ -- Note [Overlap and deriving] in GHC.Tc.Deriv.Infer. -- the theta is either the given and final theta, in standalone deriving, -- or the not-yet-simplified list of constraints together with their origin + -- The ds_skol_info is the SkolemInfo that was used to skolemise the+ -- TcTyVars (if we are inferring an instance context). The ds_user_ctxt+ -- is the UserTypeCtxt that allows error messages to know if we are in+ -- a deriving clause or a standalone deriving declaration.+ -- ds_mechanism specifies the means by which GHC derives the instance. -- See Note [Deriving strategies] in GHC.Tc.Deriv @@ -164,7 +203,7 @@ pprDerivSpec :: Outputable theta => DerivSpec theta -> SDoc pprDerivSpec (DS { ds_loc = l, ds_name = n, ds_tvs = tvs, ds_cls = c,- ds_tys = tys, ds_theta = rhs,+ ds_tys = tys, ds_theta = rhs, ds_skol_info = skol_info, ds_standalone_wildcard = wildcard, ds_mechanism = mech }) = hang (text "DerivSpec") 2 (vcat [ text "ds_loc =" <+> ppr l@@ -173,12 +212,35 @@ , text "ds_cls =" <+> ppr c , text "ds_tys =" <+> ppr tys , text "ds_theta =" <+> ppr rhs+ , text "ds_skol_info =" <+> ppr skol_info , text "ds_standalone_wildcard =" <+> ppr wildcard , text "ds_mechanism =" <+> ppr mech ]) instance Outputable theta => Outputable (DerivSpec theta) where ppr = pprDerivSpec +-- | Set the 'ds_theta' in a 'DerivSpec'.+setDerivSpecTheta :: theta' -> DerivSpec theta -> DerivSpec theta'+setDerivSpecTheta theta ds = ds{ds_theta = theta}++-- | Zonk the 'TcTyVar's in a 'DerivSpec' to 'TyVar's.+-- See @Note [What is zonking?]@ in "GHC.Tc.Utils.TcMType".+--+-- This is only used in the final zonking step when inferring+-- the context for a derived instance.+-- See @Note [Overlap and deriving]@ in "GHC.Tc.Deriv.Infer".+zonkDerivSpec :: DerivSpec ThetaType -> TcM (DerivSpec ThetaType)+zonkDerivSpec ds@(DS { ds_tvs = tvs, ds_theta = theta+ , ds_tys = tys, ds_mechanism = mechanism+ }) = do+ (ze, tvs') <- zonkTyBndrs tvs+ theta' <- zonkTcTypesToTypesX ze theta+ tys' <- zonkTcTypesToTypesX ze tys+ mechanism' <- zonkDerivSpecMechanism ze mechanism+ pure ds{ ds_tvs = tvs', ds_theta = theta'+ , ds_tys = tys', ds_mechanism = mechanism'+ }+ -- | What action to take in order to derive a class instance. -- See @Note [DerivEnv and DerivSpecMechanism]@, as well as -- @Note [Deriving strategies]@ in "GHC.Tc.Deriv".@@ -189,28 +251,9 @@ -- ^ Information about the arguments to the class in the derived -- instance, including what type constructor the last argument is -- headed by. See @Note [DerivEnv and DerivSpecMechanism]@.- , dsm_stock_gen_fn ::- SrcSpan -> [Type] -- inst_tys- -> DerivInstTys -- dsm_stock_dit- -> TcM (LHsBinds GhcPs, [LSig GhcPs], BagDerivStuff, [Name])- -- ^ This function returns four things:- --- -- 1. @LHsBinds GhcPs@: The derived instance's function bindings- -- (e.g., @compare (T x) (T y) = compare x y@)- --- -- 2. @[LSig GhcPs]@: A list of instance specific signatures/pragmas.- -- Most likely INLINE pragmas for class methods.- --- -- 3. @BagDerivStuff@: Auxiliary bindings needed to support the derived- -- instance. As examples, derived 'Generic' instances require- -- associated type family instances, and derived 'Eq' and 'Ord'- -- instances require top-level @con2tag@ functions.- -- See @Note [Auxiliary binders]@ in "GHC.Tc.Deriv.Generate".- --- -- 4. @[Name]@: A list of Names for which @-Wunused-binds@ should be- -- suppressed. This is used to suppress unused warnings for record- -- selectors when deriving 'Read', 'Show', or 'Generic'.- -- See @Note [Deriving and unused record selectors]@.+ , dsm_stock_gen_fns :: StockGenFns+ -- ^ How to generate the instance bindings and associated type family+ -- instances. } -- | @GeneralizedNewtypeDeriving@@@ -257,6 +300,44 @@ isDerivSpecVia (DerivSpecVia{}) = True isDerivSpecVia _ = False +-- | Zonk the 'TcTyVar's in a 'DerivSpecMechanism' to 'TyVar's.+-- See @Note [What is zonking?]@ in "GHC.Tc.Utils.TcMType".+--+-- This is only used in the final zonking step when inferring+-- the context for a derived instance.+-- See @Note [Overlap and deriving]@ in "GHC.Tc.Deriv.Infer".+zonkDerivSpecMechanism :: ZonkEnv -> DerivSpecMechanism -> TcM DerivSpecMechanism+zonkDerivSpecMechanism ze mechanism =+ case mechanism of+ DerivSpecStock { dsm_stock_dit = dit+ , dsm_stock_gen_fns = gen_fns+ } -> do+ dit' <- zonkDerivInstTys ze dit+ pure $ DerivSpecStock { dsm_stock_dit = dit'+ , dsm_stock_gen_fns = gen_fns+ }+ DerivSpecNewtype { dsm_newtype_dit = dit+ , dsm_newtype_rep_ty = rep_ty+ } -> do+ dit' <- zonkDerivInstTys ze dit+ rep_ty' <- zonkTcTypeToTypeX ze rep_ty+ pure $ DerivSpecNewtype { dsm_newtype_dit = dit'+ , dsm_newtype_rep_ty = rep_ty'+ }+ DerivSpecAnyClass ->+ pure DerivSpecAnyClass+ DerivSpecVia { dsm_via_cls_tys = cls_tys+ , dsm_via_inst_ty = inst_ty+ , dsm_via_ty = via_ty+ } -> do+ cls_tys' <- zonkTcTypesToTypesX ze cls_tys+ inst_ty' <- zonkTcTypeToTypeX ze inst_ty+ via_ty' <- zonkTcTypeToTypeX ze via_ty+ pure $ DerivSpecVia { dsm_via_cls_tys = cls_tys'+ , dsm_via_inst_ty = inst_ty'+ , dsm_via_ty = via_ty'+ }+ instance Outputable DerivSpecMechanism where ppr (DerivSpecStock{dsm_stock_dit = dit}) = hang (text "DerivSpecStock")@@ -401,45 +482,102 @@ -- -- See @Note [Deriving strategies]@ in "GHC.Tc.Deriv". data OriginativeDerivStatus- = CanDeriveStock -- Stock class, can derive- (SrcSpan -> [Type] -> DerivInstTys- -> TcM (LHsBinds GhcPs, [LSig GhcPs], BagDerivStuff, [Name]))+ = CanDeriveStock StockGenFns -- Stock class, can derive | StockClassError !DeriveInstanceErrReason -- Stock class, but can't do it | CanDeriveAnyClass -- See Note [Deriving any class] | NonDerivableClass -- Cannot derive with either stock or anyclass +-- | Describes how to generate instance bindings ('stock_gen_binds') and+-- associated type family instances ('stock_gen_fam_insts') for a particular+-- stock-derived instance.+data StockGenFns = StockGenFns+ { stock_gen_binds ::+ SrcSpan -> DerivInstTys+ -> TcM (LHsBinds GhcPs, [LSig GhcPs], Bag AuxBindSpec, [Name])+ -- ^ Describes how to generate instance bindings for a stock-derived+ -- instance.+ --+ -- This function takes two arguments:+ --+ -- 1. 'SrcSpan': the source location where the instance is being derived.+ -- This will eventually be instantiated with the 'ds_loc' field of a+ -- 'DerivSpec'.+ --+ -- 2. 'DerivInstTys': information about the argument types to which a+ -- class is applied in a derived instance. This will eventually be+ -- instantiated with the 'dsm_stock_dit' field of a+ -- 'DerivSpecMechanism'.+ --+ -- This function returns four things:+ --+ -- 1. @'LHsBinds' 'GhcPs'@: The derived instance's function bindings+ -- (e.g., @compare (T x) (T y) = compare x y@)+ --+ -- 2. @['LSig' 'GhcPs']@: A list of instance specific signatures/pragmas.+ -- Most likely @INLINE@ pragmas for class methods.+ --+ -- 3. @'Bag' 'AuxBindSpec'@: Auxiliary bindings needed to support the+ -- derived instance. As examples, derived 'Eq' and 'Ord' instances+ -- sometimes require top-level @con2tag@ functions.+ -- See @Note [Auxiliary binders]@ in "GHC.Tc.Deriv.Generate".+ --+ -- 4. @['Name']@: A list of Names for which @-Wunused-binds@ should be+ -- suppressed. This is used to suppress unused warnings for record+ -- selectors when deriving 'Read', 'Show', or 'Generic'.+ -- See @Note [Deriving and unused record selectors]@.+ , stock_gen_fam_insts ::+ SrcSpan -> DerivInstTys+ -> TcM [FamInst]+ -- ^ Describes how to generate associated type family instances for a+ -- stock-derived instance. This function takes the same arguments as the+ -- 'stock_gen_binds' function but returns a list of 'FamInst's instead.+ -- Generating type family instances is done separately from+ -- 'stock_gen_binds' since the type family instances must be generated+ -- before the instance bindings can be typechecked. See+ -- @Note [Staging of tcDeriving]@ in "GHC.Tc.Deriv".+ }+ -- A stock class is one either defined in the Haskell report or for which GHC -- otherwise knows how to generate code for (possibly requiring the use of a -- language extension), such as Eq, Ord, Ix, Data, Generic, etc.) --- | A 'PredType' annotated with the origin of the constraint 'CtOrigin',--- and whether or the constraint deals in types or kinds.-data PredOrigin = PredOrigin PredType CtOrigin TypeOrKind+-- | A 'PredSpec' specifies a constraint to emitted when inferring the+-- instance context for a derived instance in 'GHC.Tc.Deriv.simplifyInfer'.+data PredSpec+ = -- | An ordinary 'PredSpec' that directly stores a 'PredType', which+ -- will be emitted as a wanted constraint in the constraint solving+ -- machinery. This is the simple case, as there are no skolems,+ -- metavariables, or given constraints involved.+ SimplePredSpec+ { sps_pred :: TcPredType+ -- ^ The constraint to emit as a wanted+ , sps_origin :: CtOrigin+ -- ^ The origin of the constraint+ , sps_type_or_kind :: TypeOrKind+ -- ^ Whether the constraint is a type or kind+ }+ | -- | A special 'PredSpec' that is only used by @DeriveAnyClass@. This+ -- will check if @stps_ty_actual@ is a subtype of (i.e., more polymorphic+ -- than) @stps_ty_expected@ in the constraint solving machinery, emitting an+ -- implication constraint as a side effect. For more details on how this+ -- works, see @Note [Gathering and simplifying constraints for DeriveAnyClass]@+ -- in "GHC.Tc.Deriv.Infer".+ SubTypePredSpec+ { stps_ty_actual :: TcSigmaType+ -- ^ The actual type. In the context of @DeriveAnyClass@, this is the+ -- default method type signature.+ , stps_ty_expected :: TcSigmaType+ -- ^ The expected type. In the context of @DeriveAnyClass@, this is the+ -- original method type signature.+ , stps_origin :: CtOrigin+ -- ^ The origin of the constraint+ } --- | A list of wanted 'PredOrigin' constraints ('to_wanted_origins') to--- simplify when inferring a derived instance's context. These are used in all--- deriving strategies, but in the particular case of @DeriveAnyClass@, we--- need extra information. In particular, we need:------ * 'to_anyclass_skols', the list of type variables bound by a class method's--- regular type signature, which should be rigid.------ * 'to_anyclass_metas', the list of type variables bound by a class method's--- default type signature. These can be unified as necessary.------ * 'to_anyclass_givens', the list of constraints from a class method's--- regular type signature, which can be used to help solve constraints--- in the 'to_wanted_origins'.------ (Note that 'to_wanted_origins' will likely contain type variables from the--- derived type class or data type, neither of which will appear in--- 'to_anyclass_skols' or 'to_anyclass_metas'.)------ For all other deriving strategies, it is always the case that--- 'to_anyclass_skols', 'to_anyclass_metas', and 'to_anyclass_givens' are--- empty.------ Here is an example to illustrate this:+-- | A list of 'PredSpec' constraints to simplify when inferring a+-- derived instance's context. For the @stock@, @newtype@, and @via@ deriving+-- strategies, these will consist of 'SimplePredSpec's, and for+-- @DeriveAnyClass@, these will consist of 'SubTypePredSpec's. Here is an+-- example to illustrate the latter: -- -- @ -- class Foo a where@@ -454,76 +592,120 @@ -- data Quux q = Quux deriving anyclass Foo -- @ ----- Then it would generate two 'ThetaOrigin's, one for each method:+-- Then it would generate two 'SubTypePredSpec's, one for each method: -- -- @--- [ ThetaOrigin { to_anyclass_skols = [b]--- , to_anyclass_metas = [y]--- , to_anyclass_givens = [Ix b]--- , to_wanted_origins = [ Show (Quux q), Ix y--- , (Quux q -> b -> String) ~--- (Quux q -> y -> String)--- ] }--- , ThetaOrigin { to_anyclass_skols = []--- , to_anyclass_metas = []--- , to_anyclass_givens = [Eq (Quux q)]--- , to_wanted_origins = [ Ord (Quux q)--- , (Quux q -> Quux q -> Bool) ~--- (Quux q -> Quux q -> Bool)--- ] }+-- [ SubTypePredSpec+-- { stps_ty_actual = forall y. (Show (Quux q), Ix y) => Quux q -> y -> String+-- , stps_ty_expected = forall b. (Ix b) => Quux q -> b -> String+-- , stps_ty_origin = DerivClauseCtxt+-- }+-- , SubTypePredSpec+-- { stps_ty_actual = Ord (Quux q) => Quux q -> Quux q -> Bool+-- , stps_ty_expected = Eq (Quux q) => Quux q -> Quux q -> Bool+-- , stps_ty_origin = DerivClauseCtxt+-- } -- ] -- @ -- -- (Note that the type variable @q@ is bound by the data type @Quux@, and thus--- it appears in neither 'to_anyclass_skols' nor 'to_anyclass_metas'.)+-- appears free in the 'stps_ty_actual's and 'stps_ty_expected's.) -- -- See @Note [Gathering and simplifying constraints for DeriveAnyClass]@--- in "GHC.Tc.Deriv.Infer" for an explanation of how 'to_wanted_origins' are--- determined in @DeriveAnyClass@, as well as how 'to_anyclass_skols',--- 'to_anyclass_metas', and 'to_anyclass_givens' are used.-data ThetaOrigin- = ThetaOrigin { to_anyclass_skols :: [TyVar]- , to_anyclass_metas :: [TyVar]- , to_anyclass_givens :: ThetaType- , to_wanted_origins :: [PredOrigin] }+-- in "GHC.Tc.Deriv.Infer" for an explanation of how these 'SubTypePredSpec's+-- are used to compute implication constraints.+type ThetaSpec = [PredSpec] -instance Outputable PredOrigin where- ppr (PredOrigin ty _ _) = ppr ty -- The origin is not so interesting when debugging+instance Outputable PredSpec where+ ppr (SimplePredSpec{sps_pred = ty}) =+ hang (text "SimplePredSpec")+ 2 (vcat [ text "sps_pred" <+> ppr ty ])+ ppr (SubTypePredSpec { stps_ty_actual = ty_actual+ , stps_ty_expected = ty_expected }) =+ hang (text "SubTypePredSpec")+ 2 (vcat [ text "stps_ty_actual" <+> ppr ty_actual+ , text "stps_ty_expected" <+> ppr ty_expected+ ]) -instance Outputable ThetaOrigin where- ppr (ThetaOrigin { to_anyclass_skols = ac_skols- , to_anyclass_metas = ac_metas- , to_anyclass_givens = ac_givens- , to_wanted_origins = wanted_origins })- = hang (text "ThetaOrigin")- 2 (vcat [ text "to_anyclass_skols =" <+> ppr ac_skols- , text "to_anyclass_metas =" <+> ppr ac_metas- , text "to_anyclass_givens =" <+> ppr ac_givens- , text "to_wanted_origins =" <+> ppr wanted_origins ])+-- | Build a list of 'SimplePredSpec's, using the supplied 'CtOrigin' and+-- 'TypeOrKind' values for each 'PredType'.+mkDirectThetaSpec :: CtOrigin -> TypeOrKind -> ThetaType -> ThetaSpec+mkDirectThetaSpec origin t_or_k =+ map (\p -> SimplePredSpec+ { sps_pred = p+ , sps_origin = origin+ , sps_type_or_kind = t_or_k+ }) -mkPredOrigin :: CtOrigin -> TypeOrKind -> PredType -> PredOrigin-mkPredOrigin origin t_or_k pred = PredOrigin pred origin t_or_k+substPredSpec :: HasCallStack => TCvSubst -> PredSpec -> PredSpec+substPredSpec subst ps =+ case ps of+ SimplePredSpec { sps_pred = pred+ , sps_origin = origin+ , sps_type_or_kind = t_or_k+ }+ -> SimplePredSpec { sps_pred = substTy subst pred+ , sps_origin = origin+ , sps_type_or_kind = t_or_k+ } -mkThetaOrigin :: CtOrigin -> TypeOrKind- -> [TyVar] -> [TyVar] -> ThetaType -> ThetaType- -> ThetaOrigin-mkThetaOrigin origin t_or_k skols metas givens wanteds- = ThetaOrigin { to_anyclass_skols = skols- , to_anyclass_metas = metas- , to_anyclass_givens = givens- , to_wanted_origins = map (mkPredOrigin origin t_or_k) wanteds }+ SubTypePredSpec { stps_ty_actual = ty_actual+ , stps_ty_expected = ty_expected+ , stps_origin = origin+ }+ -> SubTypePredSpec { stps_ty_actual = substTy subst ty_actual+ , stps_ty_expected = substTy subst ty_expected+ , stps_origin = origin+ } --- A common case where the ThetaOrigin only contains wanted constraints, with--- no givens or locally scoped type variables.-mkThetaOriginFromPreds :: [PredOrigin] -> ThetaOrigin-mkThetaOriginFromPreds origins- = ThetaOrigin { to_anyclass_skols = [], to_anyclass_metas = []- , to_anyclass_givens = [], to_wanted_origins = origins }+-- | Capture wanted constraints from a 'ThetaSpec'.+captureThetaSpecConstraints ::+ UserTypeCtxt -- ^ Used to inform error messages as to whether+ -- we are in a @deriving@ clause or a standalone+ -- @deriving@ declaration+ -> ThetaSpec -- ^ The specs from which constraints will be created+ -> TcM (TcLevel, WantedConstraints)+captureThetaSpecConstraints user_ctxt theta =+ pushTcLevelM $ mk_wanteds theta+ where+ -- Create the constraints we need to solve. For stock and newtype+ -- deriving, these constraints will be simple wanted constraints+ -- like (C a, Ord b).+ -- But with DeriveAnyClass, we make an implication constraint.+ -- See Note [Gathering and simplifying constraints for DeriveAnyClass]+ -- in GHC.Tc.Deriv.Infer.+ mk_wanteds :: ThetaSpec -> TcM WantedConstraints+ mk_wanteds preds+ = do { (_, wanteds) <- captureConstraints $+ traverse_ emit_constraints preds+ ; pure wanteds } -substPredOrigin :: HasCallStack => TCvSubst -> PredOrigin -> PredOrigin-substPredOrigin subst (PredOrigin pred origin t_or_k)- = PredOrigin (substTy subst pred) origin t_or_k+ -- Emit the appropriate constraints depending on what sort of+ -- PredSpec we are dealing with.+ emit_constraints :: PredSpec -> TcM ()+ emit_constraints ps =+ case ps of+ -- For constraints like (C a, Ord b), emit the+ -- constraints directly as simple wanted constraints.+ SimplePredSpec { sps_pred = wanted+ , sps_origin = orig+ , sps_type_or_kind = t_or_k+ } -> do+ ev <- newWanted orig (Just t_or_k) wanted+ emitSimple (mkNonCanonical ev) + -- For DeriveAnyClass, check if ty_actual is a subtype of+ -- ty_expected, which emits an implication constraint as a+ -- side effect. See+ -- Note [Gathering and simplifying constraints for DeriveAnyClass].+ -- in GHC.Tc.Deriv.Infer.+ SubTypePredSpec { stps_ty_actual = ty_actual+ , stps_ty_expected = ty_expected+ , stps_origin = orig+ } -> do+ _ <- tcSubTypeSigma orig user_ctxt ty_actual ty_expected+ return ()+ {- ************************************************************************ * *@@ -542,59 +724,66 @@ -} hasStockDeriving- :: Class -> Maybe (SrcSpan- -> [Type]- -> DerivInstTys- -> TcM (LHsBinds GhcPs, [LSig GhcPs], BagDerivStuff, [Name]))+ :: Class -> Maybe StockGenFns hasStockDeriving clas = assocMaybe gen_list (getUnique clas) where- gen_list- :: [(Unique, SrcSpan- -> [Type]- -> DerivInstTys- -> TcM (LHsBinds GhcPs, [LSig GhcPs], BagDerivStuff, [Name]))]- gen_list = [ (eqClassKey, simpleM gen_Eq_binds)- , (ordClassKey, simpleM gen_Ord_binds)- , (enumClassKey, simpleM gen_Enum_binds)- , (boundedClassKey, simple gen_Bounded_binds)- , (ixClassKey, simpleM gen_Ix_binds)- , (showClassKey, read_or_show gen_Show_binds)- , (readClassKey, read_or_show gen_Read_binds)- , (dataClassKey, simpleM gen_Data_binds)- , (functorClassKey, simple gen_Functor_binds)- , (foldableClassKey, simple gen_Foldable_binds)- , (traversableClassKey, simple gen_Traversable_binds)- , (liftClassKey, simple gen_Lift_binds)- , (genClassKey, generic (gen_Generic_binds Gen0))- , (gen1ClassKey, generic (gen_Generic_binds Gen1)) ]+ gen_list :: [(Unique, StockGenFns)]+ gen_list =+ [ (eqClassKey, mk (simple_bindsM gen_Eq_binds) no_fam_insts)+ , (ordClassKey, mk (simple_bindsM gen_Ord_binds) no_fam_insts)+ , (enumClassKey, mk (simple_bindsM gen_Enum_binds) no_fam_insts)+ , (boundedClassKey, mk (simple_binds gen_Bounded_binds) no_fam_insts)+ , (ixClassKey, mk (simple_bindsM gen_Ix_binds) no_fam_insts)+ , (showClassKey, mk (read_or_show_binds gen_Show_binds) no_fam_insts)+ , (readClassKey, mk (read_or_show_binds gen_Read_binds) no_fam_insts)+ , (dataClassKey, mk (simple_bindsM gen_Data_binds) no_fam_insts)+ , (functorClassKey, mk (simple_binds gen_Functor_binds) no_fam_insts)+ , (foldableClassKey, mk (simple_binds gen_Foldable_binds) no_fam_insts)+ , (traversableClassKey, mk (simple_binds gen_Traversable_binds) no_fam_insts)+ , (liftClassKey, mk (simple_binds gen_Lift_binds) no_fam_insts)+ , (genClassKey, mk (generic_binds Gen0) (generic_fam_inst Gen0))+ , (gen1ClassKey, mk (generic_binds Gen1) (generic_fam_inst Gen1))+ ] - simple gen_fn loc _ dit- = let (binds, deriv_stuff) = gen_fn loc dit- in return (binds, [], deriv_stuff, [])+ mk gen_binds_fn gen_fam_insts_fn = StockGenFns+ { stock_gen_binds = gen_binds_fn+ , stock_gen_fam_insts = gen_fam_insts_fn+ } + simple_binds gen_fn loc dit+ = let (binds, aux_specs) = gen_fn loc dit+ in return (binds, [], aux_specs, [])+ -- Like `simple`, but monadic. The only monadic thing that these functions -- do is allocate new Uniques, which are used for generating the names of -- auxiliary bindings. -- See Note [Auxiliary binders] in GHC.Tc.Deriv.Generate.- simpleM gen_fn loc _ dit- = do { (binds, deriv_stuff) <- gen_fn loc dit- ; return (binds, [], deriv_stuff, []) }+ simple_bindsM gen_fn loc dit+ = do { (binds, aux_specs) <- gen_fn loc dit+ ; return (binds, [], aux_specs, []) } - read_or_show gen_fn loc _ dit+ read_or_show_binds gen_fn loc dit = do { let tc = dit_rep_tc dit ; fix_env <- getDataConFixityFun tc- ; let (binds, deriv_stuff) = gen_fn fix_env loc dit- field_names = all_field_names tc- ; return (binds, [], deriv_stuff, field_names) }+ ; let (binds, aux_specs) = gen_fn fix_env loc dit+ field_names = all_field_names tc+ ; return (binds, [], aux_specs, field_names) } - generic gen_fn _ inst_tys dit+ generic_binds gk loc dit = do { let tc = dit_rep_tc dit- ; fix_env <- getDataConFixityFun tc- ; (binds, sigs, faminst) <- gen_fn fix_env inst_tys dit+ ; (binds, sigs) <- gen_Generic_binds gk loc dit ; let field_names = all_field_names tc- ; return (binds, sigs, unitBag (DerivFamInst faminst), field_names) }+ ; return (binds, sigs, emptyBag, field_names) } + generic_fam_inst gk loc dit+ = do { let tc = dit_rep_tc dit+ ; fix_env <- getDataConFixityFun tc+ ; faminst <- gen_Generic_fam_inst gk fix_env loc dit+ ; return [faminst] }++ no_fam_insts _ _ = pure []+ -- See Note [Deriving and unused record selectors] all_field_names = map flSelector . concatMap dataConFieldLabels . tyConDataCons@@ -870,7 +1059,7 @@ where bad_args = [ arg_ty | con <- tyConDataCons rep_tc , arg_ty <- derivDataConInstArgTys con dit- , isLiftedType_maybe arg_ty /= Just True+ , mightBeUnliftedType arg_ty , not (ok_ty arg_ty) ] cls_key = classKey cls@@ -983,9 +1172,10 @@ ------------------------------------------------------------------ -newDerivClsInst :: ThetaType -> DerivSpec theta -> TcM ClsInst-newDerivClsInst theta (DS { ds_name = dfun_name, ds_overlap = overlap_mode- , ds_tvs = tvs, ds_cls = clas, ds_tys = tys })+newDerivClsInst :: DerivSpec ThetaType -> TcM ClsInst+newDerivClsInst (DS { ds_name = dfun_name, ds_overlap = overlap_mode+ , ds_tvs = tvs, ds_theta = theta+ , ds_cls = clas, ds_tys = tys }) = newClsInst overlap_mode dfun_name tvs theta clas tys extendLocalInstEnv :: [ClsInst] -> TcM a -> TcM a
compiler/GHC/Tc/Errors.hs view
@@ -2,7 +2,6 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} {-# OPTIONS_GHC -Wno-incomplete-record-updates #-}@@ -82,7 +81,6 @@ import Control.Monad ( unless, when, foldM, forM_ ) import Data.Foldable ( toList )-import Data.Functor ( (<&>) ) import Data.Function ( on ) import Data.List ( partition, sort, sortBy ) import Data.List.NonEmpty ( NonEmpty(..), (<|) )@@ -405,7 +403,7 @@ -- and we don't want to say it twice. Seems a bit ad-hoc = report_redundant_msg False where- report_redundant_msg :: Bool -- ^ whether to add "In ..." to the diagnostic+ report_redundant_msg :: Bool -- whether to add "In ..." to the diagnostic -> TcRn () report_redundant_msg show_info = do { lcl_env <- getLclEnv@@ -638,11 +636,23 @@ is_user_type_error item _ = isUserTypeError (errorItemPred item) - is_homo_equality _ (EqPred _ ty1 ty2) = tcTypeKind ty1 `tcEqType` tcTypeKind ty2- is_homo_equality _ _ = False+ is_homo_equality item (EqPred _ ty1 ty2)+ | FixedRuntimeRepOrigin {} <- errorItemOrigin item+ -- Constraints with FixedRuntimeRep origin must be reported using mkFRRErr.+ = False+ | otherwise+ = tcTypeKind ty1 `tcEqType` tcTypeKind ty2+ is_homo_equality _ _+ = False - is_equality _ (EqPred {}) = True- is_equality _ _ = False+ is_equality item (EqPred {})+ | FixedRuntimeRepOrigin {} <- errorItemOrigin item+ -- Constraints with FixedRuntimeRep origin must be reported using mkFRRErr.+ = False+ | otherwise+ = True+ is_equality _ _+ = False is_dict _ (ClassPred {}) = True is_dict _ _ = False@@ -650,7 +660,7 @@ is_ip _ (ClassPred cls _) = isIPClass cls is_ip _ _ = False - is_FRR item (SpecialPred ConcretePrimPred _)+ is_FRR item _ | FixedRuntimeRepOrigin {} <- errorItemOrigin item = True is_FRR _ _@@ -1040,7 +1050,9 @@ -> do { -- See Note [Deferred errors for coercion holes] let co_var = coHoleCoVar hole ; addTcEvBind ev_binds_var $ mkWantedEvBind co_var err_tm- ; fillCoercionHole hole (mkTcCoVarCo co_var) }}+ ; fillCoercionHole hole (mkTcCoVarCo co_var) }+ NoDest+ -> return () } addDeferredBinding _ _ _ = return () -- Do not set any evidence for Given mkErrorTerm :: SolverReportErrCtxt -> CtLoc -> Type -- of the error term@@ -1426,32 +1438,39 @@ ---------------- --- | Create a user-facing error message for unsolved @'Concrete#' ki@--- Wanted constraints arising from representation-polymorphism checks.+-- | Report a representation-polymorphism error to the user: `ty` should have+-- a fixed runtime representation, but doesn't. -- -- See Note [Reporting representation-polymorphism errors] in GHC.Tc.Types.Origin. mkFRRErr :: SolverReportErrCtxt -> [ErrorItem] -> TcM SolverReport mkFRRErr ctxt items- = do { -- Zonking/tidying.- ; origs <-- -- Zonk/tidy the 'CtOrigin's.+ = do { -- Zonk and tidy the error items.+ ; (_tidy_env, tidied_origins) <- zonkTidyOrigins (cec_tidy ctxt) (map errorItemOrigin items)- <&>- -- Then remove duplicates: only retain one 'CtOrigin' per representation-polymorphic type.- (nubOrdBy (nonDetCmpType `on` (snd . frr_orig_and_type)) . snd)- -- Obtain all the errors we want to report (constraints with FixedRuntimeRep origin),- -- with the corresponding types:- -- ty1 :: TYPE rep1, ty2 :: TYPE rep2, ...- ; let origs_and_tys = map frr_orig_and_type origs-- ; return $ important ctxt $ FixedRuntimeRepError origs_and_tys }+ -- Then remove duplicates: only retain one 'CtOrigin' per representation-polymorphic type.+ ; let frr_infos =+ nubOrdBy (nonDetCmpType `on` frrInfo_type) $+ zipWith frr_info tidied_origins (map errorItemPred items)+ ; return $ important ctxt $ FixedRuntimeRepError frr_infos } where - frr_orig_and_type :: CtOrigin -> (FRROrigin, Type)- frr_orig_and_type (FixedRuntimeRepOrigin ty frr_orig) = (frr_orig, ty)- frr_orig_and_type orig- = pprPanic "mkFRRErr: not a FixedRuntimeRep origin"- (text "origin =" <+> ppr orig)+ frr_info :: CtOrigin -> PredType -> FixedRuntimeRepErrorInfo+ frr_info orig pty+ | FixedRuntimeRepOrigin ty frr_orig <- orig+ = FixedRuntimeRepErrorInfo+ { frrInfo_origin = frr_orig+ , frrInfo_type = ty+ , frrInfo_isReflPrim = isIsReflPrimPred (classifyPredType pty)+ -- NB: it's useful to categorise the error messages depending on+ -- whether they were triggered by an 'IsRefl#' constraint or not,+ -- so that we can print an extra explanatory message to the user.+ --+ -- See Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete.+ }+ | otherwise+ = pprPanic "mkFRRErr: not a FixedRuntimeRep origin" $+ vcat [ text "origin:" <+> ppr orig+ , text "pty:" <+> ppr pty ] {- Note [Constraints include ...]
compiler/GHC/Tc/Errors/Hole.hs view
@@ -73,14 +73,18 @@ import GHC.Tc.Utils.Unify ( tcSubTypeSigma ) import GHC.HsToCore.Docs ( extractDocs )-import qualified Data.Map as Map-import GHC.Hs.Doc ( unpackHDS, DeclDocMap(..) )+import GHC.Hs.Doc import GHC.Unit.Module.ModIface ( ModIface_(..) )-import GHC.Iface.Load ( loadInterfaceForNameMaybe )+import GHC.Iface.Load ( loadInterfaceForName ) import GHC.Builtin.Utils (knownKeyNames) import GHC.Tc.Errors.Hole.FitTypes+import qualified Data.Set as Set+import GHC.Types.SrcLoc+import GHC.Utils.Trace (warnPprTrace)+import GHC.Data.FastString (unpackFS)+import GHC.Types.Unique.Map {-@@ -456,21 +460,40 @@ addHoleFitDocs fits = do { showDocs <- goptM Opt_ShowDocsOfHoleFits ; if showDocs- then do { (_, DeclDocMap lclDocs, _) <- getGblEnv >>= extractDocs- ; mapM (upd lclDocs) fits }+ then do { dflags <- getDynFlags+ ; mb_local_docs <- extractDocs dflags =<< getGblEnv+ ; (mods_without_docs, fits') <- mapAccumM (upd mb_local_docs) Set.empty fits+ ; report mods_without_docs+ ; return fits' } else return fits } where msg = text "GHC.Tc.Errors.Hole addHoleFitDocs"- lookupInIface name (ModIface { mi_decl_docs = DeclDocMap dmap })- = Map.lookup name dmap- upd lclDocs fit@(HoleFit {hfCand = cand}) =- do { let name = getName cand- ; doc <- if hfIsLcl fit- then pure (Map.lookup name lclDocs)- else do { mbIface <- loadInterfaceForNameMaybe msg name- ; return $ mbIface >>= lookupInIface name }- ; return $ fit {hfDoc = doc} }- upd _ fit = return fit+ upd mb_local_docs mods_without_docs fit@(HoleFit {hfCand = cand}) =+ let name = getName cand in+ do { mb_docs <- if hfIsLcl fit+ then pure mb_local_docs+ else mi_docs <$> loadInterfaceForName msg name+ ; case mb_docs of+ { Nothing -> return (Set.insert (nameOrigin name) mods_without_docs, fit)+ ; Just docs -> do+ { let doc = lookupUniqMap (docs_decls docs) name+ ; return $ (mods_without_docs, fit {hfDoc = map hsDocString <$> doc}) }}}+ upd _ mods_without_docs fit = pure (mods_without_docs, fit)+ nameOrigin name = case nameModule_maybe name of+ Just m -> Right m+ Nothing ->+ Left $ case nameSrcLoc name of+ RealSrcLoc r _ -> unpackFS $ srcLocFile r+ UnhelpfulLoc s -> unpackFS $ s+ report mods = do+ { let warning =+ text "WARNING: Couldn't find any documentation for the following modules:" $+$+ nest 2+ (fsep (punctuate comma+ (either text ppr <$> Set.toList mods)) $+$+ text "Make sure the modules are compiled with '-haddock'.")+ ; warnPprTrace (not $ Set.null mods)"addHoleFitDocs" warning (pure ())+ } -- For pretty printing hole fits, we display the name and type of the fit, -- with added '_' to represent any extra arguments in case of a non-zero@@ -517,9 +540,7 @@ then occDisp <+> tyApp else tyAppVars docs = case hfDoc of- Just d -> text "{-^" <>- (vcat . map text . lines . unpackHDS) d- <> text "-}"+ Just d -> pprHsDocStrings d _ -> empty funcInfo = ppWhen (has hfMatches && sTy) $ text "where" <+> occDisp <+> tyDisp
compiler/GHC/Tc/Gen/App.hs view
@@ -22,7 +22,7 @@ import {-# SOURCE #-} GHC.Tc.Gen.Expr( tcPolyExpr ) -import GHC.Types.Basic ( Arity )+import GHC.Types.Basic ( Arity, ExprOrPat(Expression) ) import GHC.Types.Id ( idArity, idName, hasNoBinding ) import GHC.Types.Name ( isWiredInName ) import GHC.Types.Var@@ -36,7 +36,7 @@ import GHC.Tc.Utils.Monad import GHC.Tc.Utils.Unify import GHC.Tc.Utils.Instantiate-import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep )+import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep_MustBeRefl ) import GHC.Tc.Instance.Family ( tcGetFamInstEnvs, tcLookupDataFamInst_maybe ) import GHC.Tc.Gen.HsType import GHC.Tc.Utils.TcMType@@ -547,7 +547,7 @@ -- (4): Unboxed tuples and unboxed sums || isUnboxedTupleDataCon con || isUnboxedSumDataCon con- -> check_thing con (dataConRepArity con) (FRRDataConArg con)+ -> check_thing con (dataConRepArity con) (FRRDataConArg Expression con) _ -> return () @@ -569,11 +569,11 @@ traceTc "tcApp remainingValArgs check_thing" (debug_msg thing arity) go (nb_applied_vis_val_args + 1) (nb_applied_val_args + 1) arg_tys where- go :: Int -- ^ visible value argument index, starting from 1+ go :: Int -- visible value argument index, starting from 1 -- only used to report the argument position in error messages- -> Int -- ^ value argument index, starting from 1+ -> Int -- value argument index, starting from 1 -- used to count up to the arity to ensure we don't check too many argument types- -> [(Type, AnonArgFlag)] -- ^ run-time argument types+ -> [(Type, AnonArgFlag)] -- run-time argument types -> TcM () go _ i_val _ | i_val > arity@@ -587,7 +587,7 @@ InvisArg -> go i_visval (i_val + 1) tys VisArg -> do- _concrete_ev <- hasFixedRuntimeRep (mk_frr_orig i_visval) arg_ty+ hasFixedRuntimeRep_MustBeRefl (mk_frr_orig i_visval) arg_ty go (i_visval + 1) (i_val + 1) tys -- A message containing all the relevant info, in case this functions@@ -673,15 +673,14 @@ ; return (eva { eva_arg = ValArg arg' , eva_arg_ty = Scaled mult arg_ty }) } -tcEValArg :: AppCtxt -> EValArg 'TcpInst -> TcSigmaType -> TcM (LHsExpr GhcTc)+tcEValArg :: AppCtxt -> EValArg 'TcpInst -> TcSigmaTypeFRR -> TcM (LHsExpr GhcTc) -- Typecheck one value argument of a function call tcEValArg ctxt (ValArg larg@(L arg_loc arg)) exp_arg_sigma = addArgCtxt ctxt larg $ do { arg' <- tcPolyExpr arg (mkCheckExpType exp_arg_sigma)- ; _concrete_ev <- hasFixedRuntimeRep (FRRApp arg) exp_arg_sigma ; return (L arg_loc arg') } -tcEValArg ctxt (ValArgQL { va_expr = larg@(L arg_loc arg)+tcEValArg ctxt (ValArgQL { va_expr = larg@(L arg_loc _) , va_fun = (inner_fun, fun_ctxt) , va_args = inner_args , va_ty = app_res_rho }) exp_arg_sigma@@ -689,10 +688,9 @@ do { traceTc "tcEValArgQL {" (vcat [ ppr inner_fun <+> ppr inner_args ]) ; tc_args <- tcValArgs True inner_args ; co <- unifyType Nothing app_res_rho exp_arg_sigma- ; _concrete_ev <- hasFixedRuntimeRep (FRRApp arg) exp_arg_sigma- ; traceTc "tcEValArg }" empty- ; return (L arg_loc $ mkHsWrapCo co $- rebuildHsApps inner_fun fun_ctxt tc_args) }+ ; let arg' = mkHsWrapCo co $ rebuildHsApps inner_fun fun_ctxt tc_args+ ; traceTc "tcEValArgQL }" empty+ ; return (L arg_loc arg') } {- ********************************************************************* * *@@ -741,9 +739,6 @@ VAExpansion orig _ -> addExprCtxt orig thing_inside VACall {} -> thing_inside - herald = sep [ text "The function" <+> quotes (ppr rn_fun)- , text "is applied to"]- -- Count value args only when complaining about a function -- applied to too many value args -- See Note [Herald for matchExpectedFunTys] in GHC.Tc.Utils.Unify.@@ -754,25 +749,30 @@ HsUnboundVar {} -> True _ -> False - inst_all :: ArgFlag -> Bool+ inst_all, inst_inferred, inst_none :: ArgFlag -> Bool inst_all (Invisible {}) = True inst_all Required = False - inst_inferred :: ArgFlag -> Bool inst_inferred (Invisible InferredSpec) = True inst_inferred (Invisible SpecifiedSpec) = False inst_inferred Required = False + inst_none _ = False+ inst_fun :: [HsExprArg 'TcpRn] -> ArgFlag -> Bool inst_fun [] | inst_final = inst_all- | otherwise = inst_inferred+ | otherwise = inst_none+ -- Using `inst_none` for `:type` avoids+ -- `forall {r1} (a :: TYPE r1) {r2} (b :: TYPE r2). a -> b`+ -- turning into `forall a {r2} (b :: TYPE r2). a -> b`.+ -- See #21088. inst_fun (EValArg {} : _) = inst_all inst_fun _ = inst_inferred ----------- go, go1 :: Delta- -> [HsExprArg 'TcpInst] -- Accumulator, reversed- -> [Scaled TcSigmaType] -- Value args to which applied so far+ -> [HsExprArg 'TcpInst] -- Accumulator, reversed+ -> [Scaled TcSigmaTypeFRR] -- Value args to which applied so far -> TcSigmaType -> [HsExprArg 'TcpRn] -> TcM (Delta, [HsExprArg 'TcpInst], TcSigmaType) @@ -868,10 +868,12 @@ -- Rule IARG from Fig 4 of the QL paper: go1 delta acc so_far fun_ty- (eva@(EValArg { eva_arg = ValArg arg, eva_ctxt = ctxt }) : rest_args)- = do { (wrap, arg_ty, res_ty) <- matchActualFunTySigma herald- (Just $ HsExprRnThing rn_fun)- (n_val_args, so_far) fun_ty+ (eva@(EValArg { eva_arg = ValArg arg, eva_ctxt = ctxt }) : rest_args)+ = do { (wrap, arg_ty, res_ty) <-+ matchActualFunTySigma+ (ExpectedFunTyArg (HsExprRnThing rn_fun) (unLoc arg))+ (Just $ HsExprRnThing rn_fun)+ (n_val_args, so_far) fun_ty ; (delta', arg') <- if do_ql then addArgCtxt ctxt arg $ -- Context needed for constraints@@ -1048,8 +1050,8 @@ ---------------- quickLookArg :: Delta- -> LHsExpr GhcRn -- Argument- -> Scaled TcSigmaType -- Type expected by the function+ -> LHsExpr GhcRn -- ^ Argument+ -> Scaled TcSigmaTypeFRR -- ^ Type expected by the function -> TcM (Delta, EValArg 'TcpInst) -- See Note [Quick Look at value arguments] --@@ -1088,7 +1090,7 @@ | Just {} <- tcSplitAppTy_maybe ty = True | otherwise = False -quickLookArg1 :: Bool -> Delta -> LHsExpr GhcRn -> TcSigmaType+quickLookArg1 :: Bool -> Delta -> LHsExpr GhcRn -> TcSigmaTypeFRR -> TcM (Delta, EValArg 'TcpInst) quickLookArg1 guarded delta larg@(L _ arg) arg_ty = do { let (fun@(rn_fun, fun_ctxt), rn_args) = splitHsApps arg
compiler/GHC/Tc/Gen/Arrow.hs view
@@ -22,7 +22,7 @@ import GHC.Tc.Errors.Types import GHC.Tc.Gen.Match import GHC.Tc.Gen.Head( tcCheckId )-import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep )+import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep_MustBeRefl ) import GHC.Tc.Utils.TcType import GHC.Tc.Utils.TcMType import GHC.Tc.Gen.Bind@@ -146,7 +146,7 @@ tcCmd env (L loc cmd) cmd_ty@(_, res_ty) = setSrcSpan (locA loc) $ do { cmd' <- tc_cmd env cmd cmd_ty- ; _concrete_ev <- hasFixedRuntimeRep (FRRArrow $ ArrowCmdResTy cmd) res_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRArrow $ ArrowCmdResTy cmd) res_ty ; return (L loc cmd') } tc_cmd :: CmdEnv -> HsCmd GhcRn -> CmdType -> TcM (HsCmd GhcTc)@@ -163,12 +163,18 @@ tc_cmd env in_cmd@(HsCmdCase x scrut matches) (stk, res_ty) = addErrCtxt (cmdCtxt in_cmd) $ do (scrut', scrut_ty) <- tcInferRho scrut+ hasFixedRuntimeRep_MustBeRefl+ (FRRArrow $ ArrowCmdCase { isCmdLamCase = False })+ scrut_ty matches' <- tcCmdMatches env scrut_ty matches (stk, res_ty) return (HsCmdCase x scrut' matches') tc_cmd env in_cmd@(HsCmdLamCase x matches) (stk, res_ty) = addErrCtxt (cmdCtxt in_cmd) $ do (co, [scrut_ty], stk') <- matchExpectedCmdArgs 1 stk+ hasFixedRuntimeRep_MustBeRefl+ (FRRArrow $ ArrowCmdCase { isCmdLamCase = True })+ scrut_ty matches' <- tcCmdMatches env scrut_ty matches (stk', res_ty) return (mkHsCmdWrap (mkWpCastN co) (HsCmdLamCase x matches')) @@ -223,9 +229,9 @@ ; arg' <- tcCheckMonoExpr arg arg_ty - ; _concrete_ev <- hasFixedRuntimeRep- (FRRArrow $ ArrowCmdArrApp (unLoc fun) (unLoc arg) ho_app)- fun_ty+ ; hasFixedRuntimeRep_MustBeRefl+ (FRRArrow $ ArrowCmdArrApp (unLoc fun) (unLoc arg) ho_app)+ fun_ty ; return (HsCmdArrApp fun_ty fun' arg' ho_app lr) } where@@ -251,9 +257,9 @@ do { arg_ty <- newOpenFlexiTyVarTy ; fun' <- tcCmd env fun (mkPairTy arg_ty cmd_stk, res_ty) ; arg' <- tcCheckMonoExpr arg arg_ty- ; _concrete_ev <- hasFixedRuntimeRep- (FRRArrow $ ArrowCmdApp (unLoc fun) (unLoc arg))- arg_ty+ ; hasFixedRuntimeRep_MustBeRefl+ (FRRArrow $ ArrowCmdApp (unLoc fun) (unLoc arg))+ arg_ty ; return (HsCmdApp x fun' arg') } -------------------------------------------@@ -283,12 +289,11 @@ , m_grhss = grhss' }) arg_tys = map (unrestricted . hsLPatType) pats' - ; _concrete_evs <-- zipWithM- (\ (Scaled _ arg_ty) i ->- hasFixedRuntimeRep (FRRArrow $ ArrowCmdLam i) arg_ty)- arg_tys- [1..]+ ; zipWithM_+ (\ (Scaled _ arg_ty) i ->+ hasFixedRuntimeRep_MustBeRefl (FRRArrow $ ArrowCmdLam i) arg_ty)+ arg_tys+ [1..] ; let cmd' = HsCmdLam x (MG { mg_alts = L l [match']@@ -366,7 +371,9 @@ -- | Typechecking for case command alternatives. Used for both -- 'HsCmdCase' and 'HsCmdLamCase'. tcCmdMatches :: CmdEnv- -> TcType -- ^ type of the scrutinee+ -> TcType -- ^ Type of the scrutinee.+ -- Must have a fixed RuntimeRep as per+ -- Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete -> MatchGroup GhcRn (LHsCmd GhcRn) -- ^ case alternatives -> CmdType -> TcM (MatchGroup GhcTc (LHsCmd GhcTc))
compiler/GHC/Tc/Gen/Bind.hs view
@@ -34,7 +34,7 @@ import GHC.Hs import GHC.Tc.Errors.Types import GHC.Tc.Gen.Sig-import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep )+import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep_MustBeRefl ) import GHC.Tc.Utils.Monad import GHC.Tc.Types.Origin import GHC.Tc.Utils.Env@@ -413,8 +413,8 @@ tc_scc (AcyclicSCC bind) = tc_sub_group NonRecursive [bind] tc_scc (CyclicSCC binds) = tc_sub_group Recursive binds - tc_sub_group rec_tc binds =- tcPolyBinds sig_fn prag_fn Recursive rec_tc closed binds+ tc_sub_group rec_tc binds = tcPolyBinds top_lvl sig_fn prag_fn+ Recursive rec_tc closed binds recursivePatSynErr :: SrcSpan -- ^ The location of the first pattern synonym binding@@ -437,7 +437,7 @@ } tc_single top_lvl sig_fn prag_fn lbind closed thing_inside- = do { (binds1, ids) <- tcPolyBinds sig_fn prag_fn+ = do { (binds1, ids) <- tcPolyBinds top_lvl sig_fn prag_fn NonRecursive NonRecursive closed [lbind]@@ -474,7 +474,7 @@ , bndr <- collectHsBindBinders CollNoDictBinders bind ] -------------------------tcPolyBinds :: TcSigFun -> TcPragEnv+tcPolyBinds :: TopLevelFlag -> TcSigFun -> TcPragEnv -> RecFlag -- Whether the group is really recursive -> RecFlag -- Whether it's recursive after breaking -- dependencies based on type signatures@@ -493,7 +493,7 @@ -- Knows nothing about the scope of the bindings -- None of the bindings are pattern synonyms -tcPolyBinds sig_fn prag_fn rec_group rec_tc closed bind_list+tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc closed bind_list = setSrcSpan loc $ recoverM (recoveryCode binder_names sig_fn) $ do -- Set up main recover; take advantage of any type sigs@@ -501,17 +501,16 @@ { traceTc "------------------------------------------------" Outputable.empty ; traceTc "Bindings for {" (ppr binder_names) ; dflags <- getDynFlags- ; let plan = decideGeneralisationPlan dflags bind_list closed sig_fn+ ; let plan = decideGeneralisationPlan dflags top_lvl closed sig_fn bind_list ; traceTc "Generalisation plan" (ppr plan) ; result@(_, poly_ids) <- case plan of NoGen -> tcPolyNoGen rec_tc prag_fn sig_fn bind_list InferGen mn -> tcPolyInfer rec_tc prag_fn sig_fn mn bind_list CheckGen lbind sig -> tcPolyCheck prag_fn sig lbind - ; _concrete_evs <-- mapM (\ poly_id ->- hasFixedRuntimeRep (FRRBinder $ idName poly_id) (idType poly_id))- poly_ids+ ; mapM_ (\ poly_id ->+ hasFixedRuntimeRep_MustBeRefl (FRRBinder $ idName poly_id) (idType poly_id))+ poly_ids ; traceTc "} End of bindings for" (vcat [ ppr binder_names, ppr rec_group , vcat [ppr id <+> ppr (idType id) | id <- poly_ids]@@ -638,15 +637,13 @@ , fun_ext = wrap_gen <.> wrap_res , fun_tick = tick } - export = ABE { abe_ext = noExtField- , abe_wrap = idHsWrapper+ export = ABE { abe_wrap = idHsWrapper , abe_poly = poly_id , abe_mono = poly_id2 , abe_prags = SpecPrags spec_prags } - abs_bind = L bind_loc $- AbsBinds { abs_ext = noExtField- , abs_tvs = []+ abs_bind = L bind_loc $ XHsBindsLR $+ AbsBinds { abs_tvs = [] , abs_ev_vars = [] , abs_ev_binds = [] , abs_exports = [export]@@ -733,9 +730,8 @@ ; loc <- getSrcSpanM ; let poly_ids = map abe_poly exports- abs_bind = L (noAnnSrcSpan loc) $- AbsBinds { abs_ext = noExtField- , abs_tvs = qtvs+ abs_bind = L (noAnnSrcSpan loc) $ XHsBindsLR $+ AbsBinds { abs_tvs = qtvs , abs_ev_vars = givens, abs_ev_binds = [ev_binds] , abs_exports = exports, abs_binds = binds' , abs_sig = False }@@ -751,7 +747,7 @@ -- when typechecking the bindings -> [TyVar] -> TcThetaType -- Both already zonked -> MonoBindInfo- -> TcM (ABExport GhcTc)+ -> TcM ABExport -- Only called for generalisation plan InferGen, not by CheckGen or NoGen -- -- mkExport generates exports with@@ -804,8 +800,7 @@ ; localSigWarn poly_id mb_sig - ; return (ABE { abe_ext = noExtField- , abe_wrap = wrap+ ; return (ABE { abe_wrap = wrap -- abe_wrap :: (forall qtvs. theta => mono_ty) ~ idType poly_id , abe_poly = poly_id , abe_mono = mono_id@@ -1217,7 +1212,7 @@ do { (grhss', pat_ty) <- tcInfer $ \ exp_ty -> tcGRHSsPat grhss exp_ty - ; let exp_pat_ty :: Scaled ExpSigmaType+ ; let exp_pat_ty :: Scaled ExpSigmaTypeFRR exp_pat_ty = unrestricted (mkCheckExpType pat_ty) ; (pat', mbis) <- tcLetPat (const Nothing) no_gen pat exp_pat_ty $ mapM lookupMBI bndrs@@ -1347,7 +1342,7 @@ data TcMonoBind -- Half completed; LHS done, RHS not done = TcFunBind MonoBindInfo SrcSpan (MatchGroup GhcRn (LHsExpr GhcRn)) | TcPatBind [MonoBindInfo] (LPat GhcTc) (GRHSs GhcRn (LHsExpr GhcRn))- TcSigmaType+ TcSigmaTypeFRR tcLhs :: TcSigFun -> LetBndrSpec -> HsBind GhcRn -> TcM TcMonoBind -- Only called with plan InferGen (LetBndrSpec = LetLclBndr)@@ -1652,12 +1647,12 @@ ppr (CheckGen _ s) = text "CheckGen" <+> ppr s decideGeneralisationPlan- :: DynFlags -> [LHsBind GhcRn] -> IsGroupClosed -> TcSigFun- -> GeneralisationPlan-decideGeneralisationPlan dflags lbinds closed sig_fn+ :: DynFlags -> TopLevelFlag -> IsGroupClosed -> TcSigFun+ -> [LHsBind GhcRn] -> GeneralisationPlan+decideGeneralisationPlan dflags top_lvl closed sig_fn lbinds | has_partial_sigs = InferGen (and partial_sig_mrs) | Just (bind, sig) <- one_funbind_with_sig = CheckGen bind sig- | do_not_generalise closed = NoGen+ | do_not_generalise = NoGen | otherwise = InferGen mono_restriction where binds = map unLoc lbinds@@ -1673,17 +1668,22 @@ <- mapMaybe sig_fn (collectHsBindListBinders CollNoDictBinders lbinds) , let (mtheta, _) = splitLHsQualTy (hsSigWcType hs_ty) ] - has_partial_sigs = not (null partial_sig_mrs)+ has_partial_sigs = not (null partial_sig_mrs) mono_restriction = xopt LangExt.MonomorphismRestriction dflags && any restricted binds - do_not_generalise (IsGroupClosed _ True) = False+ do_not_generalise+ | isTopLevel top_lvl = False+ -- See Note [Always generalise top-level bindings]++ | IsGroupClosed _ True <- closed = False -- The 'True' means that all of the group's -- free vars have ClosedTypeId=True; so we can ignore -- -XMonoLocalBinds, and generalise anyway- do_not_generalise _ = xopt LangExt.MonoLocalBinds dflags + | otherwise = xopt LangExt.MonoLocalBinds dflags+ -- With OutsideIn, all nested bindings are monomorphic -- except a single function binding with a signature one_funbind_with_sig@@ -1757,6 +1757,21 @@ -- These won't be in the local type env. -- Ditto class method etc from the current module +{- Note [Always generalise top-level bindings]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+It is very confusing to apply NoGen to a top level binding. Consider (#20123):+ module M where+ x = 5+ f y = (x, y)++The MR means that x=5 is not generalise, so f's binding is no Closed. So we'd+be tempted to use NoGen. But that leads to f :: Any -> (Integer, Any), which+is plain stupid.++NoGen is good when we have call sites, but not at top level, where the+function may be exported. And it's easier to grok "MonoLocalBinds" as+applying to, well, local bindings.+-} {- ********************************************************************* * *
compiler/GHC/Tc/Gen/Export.hs view
@@ -44,6 +44,7 @@ import GHC.Driver.Session import GHC.Parser.PostProcess ( setRdrNameSpace ) import Data.Either ( partitionEithers )+import GHC.Rename.Doc {- ************************************************************************@@ -316,12 +317,12 @@ , ( L loc (IEModuleContents noExtField lmod) , new_exports))) } - exports_from_item acc@(ExportAccum occs mods) (L loc ie)- | Just new_ie <- lookup_doc_ie ie- = return (Just (acc, (L loc new_ie, [])))-- | otherwise- = do (new_ie, avail) <- lookup_ie ie+ exports_from_item acc@(ExportAccum occs mods) (L loc ie) = do+ m_new_ie <- lookup_doc_ie ie+ case m_new_ie of+ Just new_ie -> return (Just (acc, (L loc new_ie, [])))+ Nothing -> do+ (new_ie, avail) <- lookup_ie ie if isUnboundName (ieName new_ie) then return Nothing -- Avoid error cascade else do@@ -396,11 +397,15 @@ return (L (locA l) name, non_flds, flds) -------------- lookup_doc_ie :: IE GhcPs -> Maybe (IE GhcRn)- lookup_doc_ie (IEGroup _ lev doc) = Just (IEGroup noExtField lev doc)- lookup_doc_ie (IEDoc _ doc) = Just (IEDoc noExtField doc)- lookup_doc_ie (IEDocNamed _ str) = Just (IEDocNamed noExtField str)- lookup_doc_ie _ = Nothing+ lookup_doc_ie :: IE GhcPs -> RnM (Maybe (IE GhcRn))+ lookup_doc_ie (IEGroup _ lev doc) = do+ doc' <- rnLHsDoc doc+ pure $ Just (IEGroup noExtField lev doc')+ lookup_doc_ie (IEDoc _ doc) = do+ doc' <- rnLHsDoc doc+ pure $ Just (IEDoc noExtField doc')+ lookup_doc_ie (IEDocNamed _ str) = pure $ Just (IEDocNamed noExtField str)+ lookup_doc_ie _ = pure Nothing -- In an export item M.T(A,B,C), we want to treat the uses of -- A,B,C as if they were M.A, M.B, M.C@@ -606,9 +611,9 @@ selErr = exportErrCtxt "pattern synonym record selector" handle_pat_syn :: SDoc- -> TyCon -- ^ Parent TyCon- -> PatSyn -- ^ Corresponding bundled PatSyn- -- and pretty printed origin+ -> TyCon -- Parent TyCon+ -> PatSyn -- Corresponding bundled PatSyn+ -- and pretty printed origin -> TcM () handle_pat_syn doc ty_con pat_syn
compiler/GHC/Tc/Gen/Expr.hs view
@@ -40,7 +40,7 @@ import GHC.Core.Multiplicity import GHC.Core.UsageEnv import GHC.Tc.Errors.Types-import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep, mkWpFun )+import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep_MustBeRefl ) import GHC.Tc.Utils.Instantiate import GHC.Tc.Gen.App import GHC.Tc.Gen.Head@@ -262,22 +262,15 @@ ; return (mkHsWrap wrap (HsLam noExtField match')) } where match_ctxt = MC { mc_what = LambdaExpr, mc_body = tcBody }- herald = sep [ text "The lambda expression" <+>- quotes (pprSetDepth (PartWay 1) $- pprMatches match),- -- The pprSetDepth makes the abstraction print briefly- text "has"]+ herald = ExpectedFunTyLam match tcExpr e@(HsLamCase x matches) res_ty = do { (wrap, matches')- <- tcMatchLambda msg match_ctxt matches res_ty- -- The laziness annotation is because we don't want to fail here- -- if there are multiple arguments+ <- tcMatchLambda herald match_ctxt matches res_ty ; return (mkHsWrap wrap $ HsLamCase x matches') } where- msg = sep [ text "The function" <+> quotes (ppr e)- , text "requires"] match_ctxt = MC { mc_what = CaseAlt, mc_body = tcBody }+ herald = ExpectedFunTyLamCase e @@ -353,7 +346,7 @@ -- This should cause an error, even though (17# :: Int#) -- is not representation-polymorphic: we don't know how -- wide the concrete representation of the sum type will be.- ; _concrete_ev <- hasFixedRuntimeRep FRRUnboxedSum res_ty+ ; hasFixedRuntimeRep_MustBeRefl FRRUnboxedSum res_ty ; return $ mkHsWrapCo coi (ExplicitSum arg_tys' alt arity expr' ) } @@ -391,6 +384,7 @@ ; (scrut', scrut_ty) <- tcScalingUsage mult $ tcInferRho scrut ; traceTc "HsCase" (ppr scrut_ty)+ ; hasFixedRuntimeRep_MustBeRefl FRRCase scrut_ty ; matches' <- tcMatchesCase match_ctxt (Scaled mult scrut_ty) matches res_ty ; return (HsCase x scrut' matches') } where@@ -867,8 +861,8 @@ = do addModFinalizersWithLclEnv mod_finalizers tcExpr expr res_ty tcExpr (HsSpliceE _ splice) res_ty = tcSpliceExpr splice res_ty-tcExpr e@(HsBracket _ brack) res_ty = tcTypedBracket e brack res_ty-tcExpr e@(HsRnBracketOut _ brack ps) res_ty = tcUntypedBracket e brack ps res_ty+tcExpr e@(HsTypedBracket _ body) res_ty = tcTypedBracket e body res_ty+tcExpr e@(HsUntypedBracket ps body) res_ty = tcUntypedBracket e body ps res_ty {- ************************************************************************@@ -881,7 +875,6 @@ tcExpr (HsOverLabel {}) ty = pprPanic "tcExpr:HsOverLabel" (ppr ty) tcExpr (SectionL {}) ty = pprPanic "tcExpr:SectionL" (ppr ty) tcExpr (SectionR {}) ty = pprPanic "tcExpr:SectionR" (ppr ty)-tcExpr (HsTcBracketOut x _ _ _) _ = dataConCantHappen x {-@@ -945,7 +938,12 @@ ; return (idHsWrapper, elt_mult, elt_ty, Just fl') } -----------------tcTupArgs :: [HsTupArg GhcRn] -> [TcSigmaType] -> TcM [HsTupArg GhcTc]+tcTupArgs :: [HsTupArg GhcRn]+ -> [TcSigmaType]+ -- ^ Argument types.+ -- This function ensures they all have+ -- a fixed runtime representation.+ -> TcM [HsTupArg GhcTc] tcTupArgs args tys = do massert (equalLength args tys) checkTupSize (length args)@@ -954,11 +952,11 @@ go :: Int -> HsTupArg GhcRn -> TcType -> TcM (HsTupArg GhcTc) go i (Missing {}) arg_ty = do { mult <- newFlexiTyVarTy multiplicityTy- ; _concrete_ev <- hasFixedRuntimeRep (FRRTupleSection i) arg_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRTupleSection i) arg_ty ; return (Missing (Scaled mult arg_ty)) } go i (Present x expr) arg_ty = do { expr' <- tcCheckPolyExpr expr arg_ty- ; _concrete_ev <- hasFixedRuntimeRep (FRRTupleArg i) arg_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRTupleArg i) arg_ty ; return (Present x expr') } ---------------------------@@ -984,14 +982,14 @@ -> SyntaxExprRn -> [SyntaxOpType] -> SyntaxOpType- -> ([TcSigmaType] -> [Mult] -> TcM a)+ -> ([TcSigmaTypeFRR] -> [Mult] -> TcM a) -> TcM (a, SyntaxExprTc) tcSyntaxOpGen orig (SyntaxExprRn op) arg_tys res_ty thing_inside = do { (expr, sigma) <- tcInferAppHead (op, VACall op 0 noSrcSpan) [] -- Ugh!! But all this code is scheduled for demolition anyway ; traceTc "tcSyntaxOpGen" (ppr op $$ ppr expr $$ ppr sigma) ; (result, expr_wrap, arg_wraps, res_wrap)- <- tcSynArgA orig sigma arg_tys res_ty $+ <- tcSynArgA orig op sigma arg_tys res_ty $ thing_inside ; traceTc "tcSyntaxOpGen" (ppr op $$ ppr expr $$ ppr sigma ) ; return (result, SyntaxExprTc { syn_expr = mkHsWrap expr_wrap expr@@ -1012,12 +1010,13 @@ -- works on "expected" types, skolemising where necessary -- See Note [tcSynArg] tcSynArgE :: CtOrigin+ -> HsExpr GhcRn -- ^ the operator to check (for error messages only) -> TcSigmaType -> SyntaxOpType -- ^ shape it is expected to have- -> ([TcSigmaType] -> [Mult] -> TcM a) -- ^ check the arguments+ -> ([TcSigmaTypeFRR] -> [Mult] -> TcM a) -- ^ check the arguments -> TcM (a, HsWrapper) -- ^ returns a wrapper :: (type of right shape) "->" (type passed in)-tcSynArgE orig sigma_ty syn_ty thing_inside+tcSynArgE orig op sigma_ty syn_ty thing_inside = do { (skol_wrap, (result, ty_wrapper)) <- tcSkolemise GenSigCtxt sigma_ty (\ rho_ty -> go rho_ty syn_ty)@@ -1055,18 +1054,20 @@ pprCtOrigin orig) ; let arg_mult = scaledMult arg_ty- ; tcSynArgA orig arg_tc_ty [] arg_shape $+ ; tcSynArgA orig op arg_tc_ty [] arg_shape $ \ arg_results arg_res_mults ->- tcSynArgE orig res_tc_ty res_shape $+ tcSynArgE orig op res_tc_ty res_shape $ \ res_results res_res_mults -> do { result <- thing_inside (arg_results ++ res_results) ([arg_mult] ++ arg_res_mults ++ res_res_mults) ; return (result, arg_tc_ty, res_tc_ty, arg_mult) }} - ; fun_wrap <- mkWpFun (arg_wrapper2 <.> arg_wrapper1) res_wrapper- (Scaled op_mult arg_ty) res_ty (WpFunSyntaxOp orig)+ ; let fun_wrap = mkWpFun (arg_wrapper2 <.> arg_wrapper1) res_wrapper+ (Scaled op_mult arg_ty) res_ty+ -- NB: arg_ty comes from matchExpectedFunTys, so it has a+ -- fixed RuntimeRep, as needed to call mkWpFun. ; return (result, match_wrapper <.> fun_wrap) } where- herald = text "This rebindable syntax expects a function with"+ herald = ExpectedFunTySyntaxOp orig op go rho_ty (SynType the_ty) = do { wrap <- tcSubTypePat orig GenSigCtxt the_ty rho_ty@@ -1076,15 +1077,16 @@ -- works on "actual" types, instantiating where necessary -- See Note [tcSynArg] tcSynArgA :: CtOrigin+ -> HsExpr GhcRn -- ^ the operator we are checking (for error messages) -> TcSigmaType -> [SyntaxOpType] -- ^ argument shapes -> SyntaxOpType -- ^ result shape- -> ([TcSigmaType] -> [Mult] -> TcM a) -- ^ check the arguments+ -> ([TcSigmaTypeFRR] -> [Mult] -> TcM a) -- ^ check the arguments -> TcM (a, HsWrapper, [HsWrapper], HsWrapper) -- ^ returns a wrapper to be applied to the original function, -- wrappers to be applied to arguments -- and a wrapper to be applied to the overall expression-tcSynArgA orig sigma_ty arg_shapes res_shape thing_inside+tcSynArgA orig op sigma_ty arg_shapes res_shape thing_inside = do { (match_wrapper, arg_tys, res_ty) <- matchActualFunTysRho herald orig Nothing (length arg_shapes) sigma_ty@@ -1095,22 +1097,22 @@ thing_inside (arg_results ++ res_results) (map scaledMult arg_tys ++ arg_res_mults) ; return (result, match_wrapper, arg_wrappers, res_wrapper) } where- herald = text "This rebindable syntax expects a function with"+ herald = ExpectedFunTySyntaxOp orig op - tc_syn_args_e :: [TcSigmaType] -> [SyntaxOpType]- -> ([TcSigmaType] -> [Mult] -> TcM a)+ tc_syn_args_e :: [TcSigmaTypeFRR] -> [SyntaxOpType]+ -> ([TcSigmaTypeFRR] -> [Mult] -> TcM a) -> TcM (a, [HsWrapper]) -- the wrappers are for arguments tc_syn_args_e (arg_ty : arg_tys) (arg_shape : arg_shapes) thing_inside = do { ((result, arg_wraps), arg_wrap)- <- tcSynArgE orig arg_ty arg_shape $ \ arg1_results arg1_mults ->- tc_syn_args_e arg_tys arg_shapes $ \ args_results args_mults ->+ <- tcSynArgE orig op arg_ty arg_shape $ \ arg1_results arg1_mults ->+ tc_syn_args_e arg_tys arg_shapes $ \ args_results args_mults -> thing_inside (arg1_results ++ args_results) (arg1_mults ++ args_mults) ; return (result, arg_wrap : arg_wraps) } tc_syn_args_e _ _ thing_inside = (, []) <$> thing_inside [] [] - tc_syn_arg :: TcSigmaType -> SyntaxOpType- -> ([TcSigmaType] -> TcM a)+ tc_syn_arg :: TcSigmaTypeFRR -> SyntaxOpType+ -> ([TcSigmaTypeFRR] -> TcM a) -> TcM (a, HsWrapper) -- the wrapper applies to the overall result tc_syn_arg res_ty SynAny thing_inside@@ -1386,9 +1388,8 @@ | Just field_ty <- assocMaybe flds_w_tys sel_name = addErrCtxt (fieldCtxt field_lbl) $ do { rhs' <- tcCheckPolyExprNC rhs field_ty- ; _concrete_ev <-- hasFixedRuntimeRep (FRRRecordUpdate (unLoc lbl) (unLoc rhs))- field_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRRecordUpdate (unLoc lbl) (unLoc rhs'))+ field_ty ; let field_id = mkUserLocal (nameOccName sel_name) (nameUnique sel_name) Many field_ty (locA loc)
compiler/GHC/Tc/Gen/Expr.hs-boot view
@@ -1,7 +1,8 @@ module GHC.Tc.Gen.Expr where import GHC.Hs ( HsExpr, LHsExpr, SyntaxExprRn , SyntaxExprTc )-import GHC.Tc.Utils.TcType ( TcRhoType, TcSigmaType, SyntaxOpType+import GHC.Tc.Utils.TcType ( TcRhoType, TcSigmaType, TcSigmaTypeFRR+ , SyntaxOpType , ExpType, ExpRhoType, ExpSigmaType ) import GHC.Tc.Types ( TcM ) import GHC.Tc.Types.Origin ( CtOrigin )@@ -32,13 +33,13 @@ -> SyntaxExprRn -> [SyntaxOpType] -- ^ shape of syntax operator arguments -> ExpType -- ^ overall result type- -> ([TcSigmaType] -> [Mult] -> TcM a) -- ^ Type check any arguments+ -> ([TcSigmaTypeFRR] -> [Mult] -> TcM a) -- ^ Type check any arguments -> TcM (a, SyntaxExprTc) tcSyntaxOpGen :: CtOrigin -> SyntaxExprRn -> [SyntaxOpType] -> SyntaxOpType- -> ([TcSigmaType] -> [Mult] -> TcM a)+ -> ([TcSigmaTypeFRR] -> [Mult] -> TcM a) -> TcM (a, SyntaxExprTc)
compiler/GHC/Tc/Gen/Foreign.hs view
@@ -266,22 +266,23 @@ tcCheckFIType :: [Scaled Type] -> Type -> ForeignImport -> TcM ForeignImport -tcCheckFIType arg_tys res_ty (CImport (L lc cconv) safety mh l@(CLabel _) src)+tcCheckFIType arg_tys res_ty idecl@(CImport (L lc cconv) safety mh l@(CLabel _) src) -- Foreign import label- = do checkCg checkCOrAsmOrLlvmOrInterp+ = do checkCg (Right idecl) checkCOrAsmOrLlvmOrInterp -- NB check res_ty not sig_ty! -- In case sig_ty is (forall a. ForeignPtr a)- check (isFFILabelTy (mkVisFunTys arg_tys res_ty)) (illegalForeignTyErr Outputable.empty)- cconv' <- checkCConv cconv+ check (isFFILabelTy (mkVisFunTys arg_tys res_ty))+ (TcRnIllegalForeignType Nothing)+ cconv' <- checkCConv (Right idecl) cconv return (CImport (L lc cconv') safety mh l src) -tcCheckFIType arg_tys res_ty (CImport (L lc cconv) safety mh CWrapper src) = do+tcCheckFIType arg_tys res_ty idecl@(CImport (L lc cconv) safety mh CWrapper src) = do -- Foreign wrapper (former f.e.d.) -- The type must be of the form ft -> IO (FunPtr ft), where ft is a valid -- foreign type. For legacy reasons ft -> IO (Ptr ft) is accepted, too. -- The use of the latter form is DEPRECATED, though.- checkCg checkCOrAsmOrLlvmOrInterp- cconv' <- checkCConv cconv+ checkCg (Right idecl) checkCOrAsmOrLlvmOrInterp+ cconv' <- checkCConv (Right idecl) cconv case arg_tys of [Scaled arg1_mult arg1_ty] -> do checkNoLinearFFI arg1_mult@@ -290,73 +291,66 @@ checkForeignRes mustBeIO checkSafe (isFFIDynTy arg1_ty) res_ty where (arg1_tys, res1_ty) = tcSplitFunTys arg1_ty- _ -> addErrTc (illegalForeignTyErr Outputable.empty (text "One argument expected"))+ _ -> addErrTc (TcRnIllegalForeignType Nothing OneArgExpected) return (CImport (L lc cconv') safety mh CWrapper src) tcCheckFIType arg_tys res_ty idecl@(CImport (L lc cconv) (L ls safety) mh (CFunction target) src) | isDynamicTarget target = do -- Foreign import dynamic- checkCg checkCOrAsmOrLlvmOrInterp- cconv' <- checkCConv cconv+ checkCg (Right idecl) checkCOrAsmOrLlvmOrInterp+ cconv' <- checkCConv (Right idecl) cconv case arg_tys of -- The first arg must be Ptr or FunPtr [] ->- addErrTc (illegalForeignTyErr Outputable.empty (text "At least one argument expected"))+ addErrTc (TcRnIllegalForeignType Nothing AtLeastOneArgExpected) (Scaled arg1_mult arg1_ty:arg_tys) -> do dflags <- getDynFlags let curried_res_ty = mkVisFunTys arg_tys res_ty checkNoLinearFFI arg1_mult check (isFFIDynTy curried_res_ty arg1_ty)- (illegalForeignTyErr argument)+ (TcRnIllegalForeignType (Just Arg)) checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys checkForeignRes nonIOok checkSafe (isFFIImportResultTy dflags) res_ty return $ CImport (L lc cconv') (L ls safety) mh (CFunction target) src | cconv == PrimCallConv = do dflags <- getDynFlags checkTc (xopt LangExt.GHCForeignImportPrim dflags)- (TcRnUnknownMessage $ mkPlainError noHints $- text "Use GHCForeignImportPrim to allow `foreign import prim'.")- checkCg checkCOrAsmOrLlvmOrInterp- checkCTarget target+ (TcRnForeignImportPrimExtNotSet idecl)+ checkCg (Right idecl) checkCOrAsmOrLlvmOrInterp+ checkCTarget idecl target checkTc (playSafe safety)- (TcRnUnknownMessage $ mkPlainError noHints $- text "The safe/unsafe annotation should not be used with `foreign import prim'.")+ (TcRnForeignImportPrimSafeAnn idecl) checkForeignArgs (isFFIPrimArgumentTy dflags) arg_tys -- prim import result is more liberal, allows (#,,#) checkForeignRes nonIOok checkSafe (isFFIPrimResultTy dflags) res_ty return idecl | otherwise = do -- Normal foreign import- checkCg checkCOrAsmOrLlvmOrInterp- cconv' <- checkCConv cconv- checkCTarget target+ checkCg (Right idecl) checkCOrAsmOrLlvmOrInterp+ cconv' <- checkCConv (Right idecl) cconv+ checkCTarget idecl target dflags <- getDynFlags checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys checkForeignRes nonIOok checkSafe (isFFIImportResultTy dflags) res_ty- checkMissingAmpersand (map scaledThing arg_tys) res_ty+ checkMissingAmpersand idecl (map scaledThing arg_tys) res_ty case target of StaticTarget _ _ _ False | not (null arg_tys) ->- addErrTc (TcRnUnknownMessage $ mkPlainError noHints $- text "`value' imports cannot have function types")+ addErrTc (TcRnForeignFunctionImportAsValue idecl) _ -> return () return $ CImport (L lc cconv') (L ls safety) mh (CFunction target) src - -- This makes a convenient place to check -- that the C identifier is valid for C-checkCTarget :: CCallTarget -> TcM ()-checkCTarget (StaticTarget _ str _ _) = do- checkCg checkCOrAsmOrLlvmOrInterp- checkTc (isCLabelString str) (badCName str)--checkCTarget DynamicTarget = panic "checkCTarget DynamicTarget"+checkCTarget :: ForeignImport -> CCallTarget -> TcM ()+checkCTarget idecl (StaticTarget _ str _ _) = do+ checkCg (Right idecl) checkCOrAsmOrLlvmOrInterp+ checkTc (isCLabelString str) (TcRnInvalidCIdentifier str) +checkCTarget _ DynamicTarget = panic "checkCTarget DynamicTarget" -checkMissingAmpersand :: [Type] -> Type -> TcM ()-checkMissingAmpersand arg_tys res_ty+checkMissingAmpersand :: ForeignImport -> [Type] -> Type -> TcM ()+checkMissingAmpersand idecl arg_tys res_ty | null arg_tys && isFunPtrTy res_ty- = addDiagnosticTc $ TcRnUnknownMessage $- mkPlainDiagnostic (WarningWithFlag Opt_WarnDodgyForeignImports) noHints- (text "possible missing & in foreign import of FunPtr")+ = addDiagnosticTc $ TcRnFunPtrImportWithoutAmpersand idecl | otherwise = return () @@ -420,10 +414,10 @@ -- ------------ Checking argument types for foreign export ---------------------- tcCheckFEType :: Type -> ForeignExport -> TcM ForeignExport-tcCheckFEType sig_ty (CExport (L l (CExportStatic esrc str cconv)) src) = do- checkCg checkCOrAsmOrLlvm- checkTc (isCLabelString str) (badCName str)- cconv' <- checkCConv cconv+tcCheckFEType sig_ty edecl@(CExport (L l (CExportStatic esrc str cconv)) src) = do+ checkCg (Left edecl) checkCOrAsmOrLlvm+ checkTc (isCLabelString str) (TcRnInvalidCIdentifier str)+ cconv' <- checkCConv (Left edecl) cconv checkForeignArgs isFFIExternalTy arg_tys checkForeignRes nonIOok noCheckSafe isFFIExportResultTy res_ty return (CExport (L l (CExportStatic esrc str cconv')) src)@@ -441,16 +435,16 @@ -} ------------ Checking argument types for foreign import -----------------------checkForeignArgs :: (Type -> Validity) -> [Scaled Type] -> TcM ()+checkForeignArgs :: (Type -> Validity' IllegalForeignTypeReason) -> [Scaled Type] -> TcM () checkForeignArgs pred tys = mapM_ go tys where go (Scaled mult ty) = checkNoLinearFFI mult >>- check (pred ty) (illegalForeignTyErr argument)+ check (pred ty) (TcRnIllegalForeignType (Just Arg)) checkNoLinearFFI :: Mult -> TcM () -- No linear types in FFI (#18472) checkNoLinearFFI Many = return ()-checkNoLinearFFI _ = addErrTc $ illegalForeignTyErr argument- (text "Linear types are not supported in FFI declarations, see #18472")+checkNoLinearFFI _ = addErrTc $ TcRnIllegalForeignType (Just Arg)+ LinearTypesNotAllowed ------------ Checking result types for foreign calls ---------------------- -- | Check that the type has the form@@ -461,27 +455,28 @@ -- We also check that the Safe Haskell condition of FFI imports having -- results in the IO monad holds. ---checkForeignRes :: Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()+checkForeignRes :: Bool -> Bool -> (Type -> Validity' IllegalForeignTypeReason) -> Type -> TcM () checkForeignRes non_io_result_ok check_safe pred_res_ty ty | Just (_, res_ty) <- tcSplitIOType_maybe ty = -- Got an IO result type, that's always fine!- check (pred_res_ty res_ty) (illegalForeignTyErr result)+ check (pred_res_ty res_ty)+ (TcRnIllegalForeignType (Just Result)) -- We disallow nested foralls in foreign types -- (at least, for the time being). See #16702. | tcIsForAllTy ty- = addErrTc $ illegalForeignTyErr result (text "Unexpected nested forall")+ = addErrTc $ TcRnIllegalForeignType (Just Result) UnexpectedNestedForall -- Case for non-IO result type with FFI Import | not non_io_result_ok- = addErrTc $ illegalForeignTyErr result (text "IO result type expected")+ = addErrTc $ TcRnIllegalForeignType (Just Result) IOResultExpected | otherwise = do { dflags <- getDynFlags ; case pred_res_ty ty of -- Handle normal typecheck fail, we want to handle this first and -- only report safe haskell errors if the normal type check is OK.- NotValid msg -> addErrTc $ illegalForeignTyErr result msg+ NotValid msg -> addErrTc $ TcRnIllegalForeignType (Just Result) msg -- handle safe infer fail _ | check_safe && safeInferOn dflags@@ -489,13 +484,10 @@ -- handle safe language typecheck fail _ | check_safe && safeLanguageOn dflags- -> addErrTc (illegalForeignTyErr result safeHsErr)+ -> addErrTc (TcRnIllegalForeignType (Just Result) SafeHaskellMustBeInIO) -- success! non-IO return is fine _ -> return () }- where- safeHsErr =- text "Safe Haskell is on, all FFI imports must be in the IO monad" nonIOok, mustBeIO :: Bool nonIOok = True@@ -506,84 +498,64 @@ noCheckSafe = False -- | Checking a supported backend is in use-checkCOrAsmOrLlvm :: Backend -> Validity+checkCOrAsmOrLlvm :: Backend -> Validity' ExpectedBackends checkCOrAsmOrLlvm ViaC = IsValid checkCOrAsmOrLlvm NCG = IsValid checkCOrAsmOrLlvm LLVM = IsValid-checkCOrAsmOrLlvm _- = NotValid (text "requires unregisterised, llvm (-fllvm) or native code generation (-fasm)")+checkCOrAsmOrLlvm _ = NotValid COrAsmOrLlvm -- | Checking a supported backend is in use-checkCOrAsmOrLlvmOrInterp :: Backend -> Validity+checkCOrAsmOrLlvmOrInterp :: Backend -> Validity' ExpectedBackends checkCOrAsmOrLlvmOrInterp ViaC = IsValid checkCOrAsmOrLlvmOrInterp NCG = IsValid checkCOrAsmOrLlvmOrInterp LLVM = IsValid checkCOrAsmOrLlvmOrInterp Interpreter = IsValid-checkCOrAsmOrLlvmOrInterp _- = NotValid (text "requires interpreted, unregisterised, llvm or native code generation")+checkCOrAsmOrLlvmOrInterp _ = NotValid COrAsmOrLlvmOrInterp -checkCg :: (Backend -> Validity) -> TcM ()-checkCg check = do+checkCg :: Either ForeignExport ForeignImport -> (Backend -> Validity' ExpectedBackends) -> TcM ()+checkCg decl check = do dflags <- getDynFlags let bcknd = backend dflags case bcknd of NoBackend -> return () _ -> case check bcknd of- IsValid -> return ()- NotValid err ->- addErrTc (TcRnUnknownMessage $ mkPlainError noHints $ text "Illegal foreign declaration:" <+> err)+ IsValid -> return ()+ NotValid expectedBcknd ->+ addErrTc $ TcRnIllegalForeignDeclBackend decl bcknd expectedBcknd -- Calling conventions -checkCConv :: CCallConv -> TcM CCallConv-checkCConv CCallConv = return CCallConv-checkCConv CApiConv = return CApiConv-checkCConv StdCallConv = do dflags <- getDynFlags- let platform = targetPlatform dflags- if platformArch platform == ArchX86- then return StdCallConv- else do -- This is a warning, not an error. see #3336- let msg = TcRnUnknownMessage $- mkPlainDiagnostic (WarningWithFlag Opt_WarnUnsupportedCallingConventions)- noHints- (text "the 'stdcall' calling convention is unsupported on this platform," $$ text "treating as ccall")- addDiagnosticTc msg- return CCallConv-checkCConv PrimCallConv = do- addErrTc $ TcRnUnknownMessage $ mkPlainError noHints- (text "The `prim' calling convention can only be used with `foreign import'")+checkCConv :: Either ForeignExport ForeignImport -> CCallConv -> TcM CCallConv+checkCConv _ CCallConv = return CCallConv+checkCConv _ CApiConv = return CApiConv+checkCConv decl StdCallConv = do+ dflags <- getDynFlags+ let platform = targetPlatform dflags+ if platformArch platform == ArchX86+ then return StdCallConv+ else do -- This is a warning, not an error. see #3336+ let msg = TcRnUnsupportedCallConv decl StdCallConvUnsupported+ addDiagnosticTc msg+ return CCallConv+checkCConv decl PrimCallConv = do+ addErrTc $ TcRnUnsupportedCallConv decl PrimCallConvUnsupported return PrimCallConv-checkCConv JavaScriptCallConv = do dflags <- getDynFlags- if platformArch (targetPlatform dflags) == ArchJavaScript- then return JavaScriptCallConv- else do- addErrTc $ TcRnUnknownMessage $ mkPlainError noHints $- (text "The `javascript' calling convention is unsupported on this platform")- return JavaScriptCallConv+checkCConv decl JavaScriptCallConv = do+ dflags <- getDynFlags+ if platformArch (targetPlatform dflags) == ArchJavaScript+ then return JavaScriptCallConv+ else do+ addErrTc $ TcRnUnsupportedCallConv decl JavaScriptCallConvUnsupported+ return JavaScriptCallConv -- Warnings -check :: Validity -> (SDoc -> TcRnMessage) -> TcM ()-check IsValid _ = return ()-check (NotValid doc) err_fn = addErrTc (err_fn doc)--illegalForeignTyErr :: SDoc -> SDoc -> TcRnMessage-illegalForeignTyErr arg_or_res extra- = TcRnUnknownMessage $ mkPlainError noHints $ hang msg 2 extra- where- msg = hsep [ text "Unacceptable", arg_or_res- , text "type in foreign declaration:"]---- Used for 'arg_or_res' argument to illegalForeignTyErr-argument, result :: SDoc-argument = text "argument"-result = text "result"--badCName :: CLabelString -> TcRnMessage-badCName target- = TcRnUnknownMessage $ mkPlainError noHints $- sep [quotes (ppr target) <+> text "is not a valid C identifier"]+check :: Validity' IllegalForeignTypeReason+ -> (IllegalForeignTypeReason -> TcRnMessage)+ -> TcM ()+check IsValid _ = return ()+check (NotValid reason) mkMessage = addErrTc (mkMessage reason) foreignDeclCtxt :: ForeignDecl GhcRn -> SDoc foreignDeclCtxt fo
compiler/GHC/Tc/Gen/Head.hs view
@@ -675,14 +675,17 @@ -- where fromInteger is gotten by looking up from_name, and -- the (3 :: Integer) is returned by mkOverLit -- Ditto the string literal "foo" to (fromString ("foo" :: String))- do { from_id <- tcLookupId from_name- ; (wrap1, from_ty) <- topInstantiate orig (idType from_id)-+ do { hs_lit <- mkOverLit val+ ; from_id <- tcLookupId from_name+ ; (wrap1, from_ty) <- topInstantiate (LiteralOrigin lit) (idType from_id)+ ; let+ thing = NameThing from_name+ mb_thing = Just thing+ herald = ExpectedFunTyArg thing (HsLit noAnn hs_lit) ; (wrap2, sarg_ty, res_ty) <- matchActualFunTySigma herald mb_thing (1, []) from_ty- ; hs_lit <- mkOverLit val- ; co <- unifyType mb_thing (hsLitType hs_lit) (scaledThing sarg_ty) + ; co <- unifyType mb_thing (hsLitType hs_lit) (scaledThing sarg_ty) ; let lit_expr = L (l2l loc) $ mkHsWrapCo co $ HsLit noAnn hs_lit from_expr = mkHsWrap (wrap2 <.> wrap1) $@@ -692,12 +695,6 @@ , ol_witness = witness , ol_type = res_ty } } ; return (HsOverLit noAnn lit', res_ty) }- where- orig = LiteralOrigin lit- mb_thing = Just (NameThing from_name)- herald = sep [ text "The function" <+> quotes (ppr from_name)- , text "is applied to"]- {- ********************************************************************* * *
compiler/GHC/Tc/Gen/Match.hs view
@@ -49,7 +49,7 @@ import GHC.Tc.Utils.TcMType import GHC.Tc.Utils.TcType import GHC.Tc.Gen.Bind-import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep )+import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep_MustBeRefl ) import GHC.Tc.Utils.Unify import GHC.Tc.Types.Origin import GHC.Tc.Types.Evidence@@ -121,8 +121,7 @@ where fun_name = idName (unLoc fun_id) arity = matchGroupArity matches- herald = text "The equation(s) for"- <+> quotes (ppr fun_name) <+> text "have"+ herald = ExpectedFunTyMatches (NameThing fun_name) matches ctxt = GenSigCtxt -- Was: FunSigCtxt fun_name True -- But that's wrong for f :: Int -> forall a. blah what = FunRhs { mc_fun = fun_id, mc_fixity = Prefix, mc_strictness = strictness }@@ -145,10 +144,10 @@ -} tcMatchesCase :: (AnnoBody body) =>- TcMatchCtxt body -- Case context- -> Scaled TcSigmaType -- Type of scrutinee- -> MatchGroup GhcRn (LocatedA (body GhcRn)) -- The case alternatives- -> ExpRhoType -- Type of whole case expressions+ TcMatchCtxt body -- ^ Case context+ -> Scaled TcSigmaTypeFRR -- ^ Type of scrutinee+ -> MatchGroup GhcRn (LocatedA (body GhcRn)) -- ^ The case alternatives+ -> ExpRhoType -- ^ Type of the whole case expression -> TcM (MatchGroup GhcTc (LocatedA (body GhcTc))) -- Translated alternatives -- wrapper goes from MatchGroup's ty to expected ty@@ -156,7 +155,7 @@ tcMatchesCase ctxt (Scaled scrut_mult scrut_ty) matches res_ty = tcMatches ctxt [Scaled scrut_mult (mkCheckExpType scrut_ty)] res_ty matches -tcMatchLambda :: SDoc -- see Note [Herald for matchExpectedFunTys] in GHC.Tc.Utils.Unify+tcMatchLambda :: ExpectedFunTyOrigin -- see Note [Herald for matchExpectedFunTys] in GHC.Tc.Utils.Unify -> TcMatchCtxt HsExpr -> MatchGroup GhcRn (LHsExpr GhcRn) -> ExpRhoType@@ -213,8 +212,8 @@ -- | Type-check a MatchGroup. tcMatches :: (AnnoBody body ) => TcMatchCtxt body- -> [Scaled ExpSigmaType] -- Expected pattern types- -> ExpRhoType -- Expected result-type of the Match.+ -> [Scaled ExpSigmaTypeFRR] -- ^ Expected pattern types.+ -> ExpRhoType -- ^ Expected result-type of the Match. -> MatchGroup GhcRn (LocatedA (body GhcRn)) -> TcM (MatchGroup GhcTc (LocatedA (body GhcTc))) @@ -227,10 +226,6 @@ = do { tcEmitBindingUsage bottomUE ; pat_tys <- mapM scaledExpTypeToType pat_tys ; rhs_ty <- expTypeToType rhs_ty- ; _concrete_evs <- zipWithM- (\ i (Scaled _ pat_ty) ->- hasFixedRuntimeRep (FRRMatch (mc_what ctxt) i) pat_ty)- [1..] pat_tys ; return (MG { mg_alts = L l [] , mg_ext = MatchGroupTc pat_tys rhs_ty , mg_origin = origin }) }@@ -241,10 +236,6 @@ ; tcEmitBindingUsage $ supUEs usages ; pat_tys <- mapM readScaledExpType pat_tys ; rhs_ty <- readExpType rhs_ty- ; _concrete_evs <- zipWithM- (\ i (Scaled _ pat_ty) ->- hasFixedRuntimeRep (FRRMatch (mc_what ctxt) i) pat_ty)- [1..] pat_tys ; return (MG { mg_alts = L l matches' , mg_ext = MatchGroupTc pat_tys rhs_ty , mg_origin = origin }) }@@ -440,7 +431,7 @@ -- two multiplicity to still be the same. (rhs', rhs_ty) <- tcScalingUsage Many $ tcInferRhoNC rhs -- Stmt has a context already- ; _concrete_ev <- hasFixedRuntimeRep FRRBindStmtGuard rhs_ty+ ; hasFixedRuntimeRep_MustBeRefl FRRBindStmtGuard rhs_ty ; (pat', thing) <- tcCheckPat_O (StmtCtxt ctxt) (lexprCtOrigin rhs) pat (unrestricted rhs_ty) $ thing_inside res_ty@@ -602,7 +593,7 @@ thing_inside (mkCheckExpType new_res_ty) ; return (rhs_ty, rhs', pat_mult, pat', thing, new_res_ty) } - ; _concrete_ev <- hasFixedRuntimeRep (FRRBindStmt MonadComprehension) rhs_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRBindStmt MonadComprehension) rhs_ty -- If (but only if) the pattern can fail, typecheck the 'fail' operator ; fail_op' <- fmap join . forM (xbsrn_failOp xbsrn) $ \fail ->@@ -638,9 +629,9 @@ ; thing <- tcScalingUsage fun_mult $ thing_inside (mkCheckExpType new_res_ty) ; return (thing, rhs', rhs_ty, new_res_ty, test_ty, guard_op') } - ; _evTerm1 <- hasFixedRuntimeRep FRRBodyStmtGuard test_ty- ; _evTerm2 <- hasFixedRuntimeRep (FRRBodyStmt MonadComprehension 1) rhs_ty- ; _evTerm3 <- hasFixedRuntimeRep (FRRBodyStmt MonadComprehension 2) new_res_ty+ ; hasFixedRuntimeRep_MustBeRefl FRRBodyStmtGuard test_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRBodyStmt MonadComprehension 1) rhs_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRBodyStmt MonadComprehension 2) new_res_ty ; return (BodyStmt rhs_ty rhs' then_op' guard_op', thing) } @@ -876,7 +867,7 @@ thing_inside (mkCheckExpType new_res_ty) ; return (rhs_ty, rhs', pat_mult, pat', new_res_ty, thing) } - ; _concrete_ev <- hasFixedRuntimeRep (FRRBindStmt DoNotation) rhs_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRBindStmt DoNotation) rhs_ty -- If (but only if) the pattern can fail, typecheck the 'fail' operator ; fail_op' <- fmap join . forM (xbsrn_failOp xbsrn) $ \fail ->@@ -910,8 +901,8 @@ do { rhs' <- tcScalingUsage rhs_mult $ tcCheckMonoExprNC rhs rhs_ty ; thing <- tcScalingUsage fun_mult $ thing_inside (mkCheckExpType new_res_ty) ; return (rhs', rhs_ty, new_res_ty, thing) }- ; _evTerm1 <- hasFixedRuntimeRep (FRRBodyStmt DoNotation 1) rhs_ty- ; _evTerm2 <- hasFixedRuntimeRep (FRRBodyStmt DoNotation 2) new_res_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRBodyStmt DoNotation 1) rhs_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRBodyStmt DoNotation 2) new_res_ty ; return (BodyStmt rhs_ty rhs' then_op' noSyntaxExpr, thing) } tcDoStmt ctxt (RecStmt { recS_stmts = L l stmts, recS_later_ids = later_names
compiler/GHC/Tc/Gen/Pat.hs view
@@ -35,7 +35,6 @@ import GHC.Tc.Errors.Types import GHC.Tc.Utils.Zonk import GHC.Tc.Gen.Sig( TcPragEnv, lookupPragEnv, addInlinePrags )-import GHC.Tc.Utils.Concrete ( mkWpFun ) import GHC.Tc.Utils.Monad import GHC.Tc.Utils.Instantiate import GHC.Types.Error@@ -44,6 +43,7 @@ import GHC.Types.Name import GHC.Types.Name.Reader import GHC.Core.Multiplicity+import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep_MustBeRefl ) import GHC.Tc.Utils.Env import GHC.Tc.Utils.TcMType import GHC.Tc.Validity( arityErr )@@ -83,7 +83,7 @@ tcLetPat :: (Name -> Maybe TcId) -> LetBndrSpec- -> LPat GhcRn -> Scaled ExpSigmaType+ -> LPat GhcRn -> Scaled ExpSigmaTypeFRR -> TcM a -> TcM (LPat GhcTc, a) tcLetPat sig_fn no_gen pat pat_ty thing_inside@@ -99,9 +99,9 @@ ----------------- tcPats :: HsMatchContext GhcTc- -> [LPat GhcRn] -- Patterns,- -> [Scaled ExpSigmaType] -- and their types- -> TcM a -- and the checker for the body+ -> [LPat GhcRn] -- ^ atterns+ -> [Scaled ExpSigmaTypeFRR] -- ^ types of the patterns+ -> TcM a -- ^ checker for the body -> TcM ([LPat GhcTc], a) -- This is the externally-callable wrapper function@@ -130,7 +130,7 @@ penv = PE { pe_lazy = False, pe_ctxt = LamPat ctxt, pe_orig = PatOrigin } tcCheckPat :: HsMatchContext GhcTc- -> LPat GhcRn -> Scaled TcSigmaType+ -> LPat GhcRn -> Scaled TcSigmaTypeFRR -> TcM a -- Checker for body -> TcM (LPat GhcTc, a) tcCheckPat ctxt = tcCheckPat_O ctxt PatOrigin@@ -138,7 +138,7 @@ -- | A variant of 'tcPat' that takes a custom origin tcCheckPat_O :: HsMatchContext GhcTc -> CtOrigin -- ^ origin to use if the type needs inst'ing- -> LPat GhcRn -> Scaled TcSigmaType+ -> LPat GhcRn -> Scaled TcSigmaTypeFRR -> TcM a -- Checker for body -> TcM (LPat GhcTc, a) tcCheckPat_O ctxt orig pat (Scaled pat_mult pat_ty) thing_inside@@ -204,7 +204,7 @@ * * ********************************************************************* -} -tcPatBndr :: PatEnv -> Name -> Scaled ExpSigmaType -> TcM (HsWrapper, TcId)+tcPatBndr :: PatEnv -> Name -> Scaled ExpSigmaTypeFRR -> TcM (HsWrapper, TcId) -- (coi, xp) = tcPatBndr penv x pat_ty -- Then coi : pat_ty ~ typeof(xp) --@@ -331,7 +331,7 @@ ; loop penv args } ---------------------tc_lpat :: Scaled ExpSigmaType+tc_lpat :: Scaled ExpSigmaTypeFRR -> Checker (LPat GhcRn) (LPat GhcTc) tc_lpat pat_ty penv (L span pat) thing_inside = setSrcSpanA span $@@ -339,7 +339,7 @@ thing_inside ; return (L span pat', res) } -tc_lpats :: [Scaled ExpSigmaType]+tc_lpats :: [Scaled ExpSigmaTypeFRR] -> Checker [LPat GhcRn] [LPat GhcTc] tc_lpats tys penv pats = assertPpr (equalLength pats tys) (ppr pats $$ ppr tys) $@@ -352,7 +352,7 @@ checkManyPattern :: Scaled a -> TcM HsWrapper checkManyPattern pat_ty = tcSubMult NonLinearPatternOrigin Many (scaledMult pat_ty) -tc_pat :: Scaled ExpSigmaType+tc_pat :: Scaled ExpSigmaTypeFRR -- ^ Fully refined result type -> Checker (Pat GhcRn) (Pat GhcTc) -- ^ Translated pattern@@ -430,7 +430,7 @@ -- Note [View patterns and polymorphism] -- Expression must be a function- ; let herald = text "A view pattern expression expects"+ ; let herald = ExpectedFunTyViewPat $ unLoc expr ; (expr_wrap1, Scaled _mult inf_arg_ty, inf_res_sigma) <- matchActualFunTySigma herald (Just . HsExprRnThing $ unLoc expr) (1,[]) expr_ty -- See Note [View patterns and polymorphism]@@ -445,10 +445,12 @@ ; let Scaled w h_pat_ty = pat_ty ; pat_ty <- readExpType h_pat_ty- ; expr_wrap2' <- mkWpFun expr_wrap2 idHsWrapper- (Scaled w pat_ty) inf_res_sigma (WpFunViewPat $ unLoc expr)- -- expr_wrap2' :: (inf_arg_ty -> inf_res_sigma) "->"- -- (pat_ty -> inf_res_sigma)+ ; let expr_wrap2' = mkWpFun expr_wrap2 idHsWrapper+ (Scaled w pat_ty) inf_res_sigma+ -- expr_wrap2' :: (inf_arg_ty -> inf_res_sigma) "->"+ -- (pat_ty -> inf_res_sigma)+ -- NB: pat_ty comes from matchActualFunTySigma, so it has a+ -- fixed RuntimeRep, as needed to call mkWpFun. ; let expr_wrap = expr_wrap2' <.> expr_wrap1 <.> mult_wrap @@ -855,7 +857,7 @@ -- with scrutinee of type (T ty) tcConPat :: PatEnv -> LocatedN Name- -> Scaled ExpSigmaType -- Type of the pattern+ -> Scaled ExpSigmaTypeFRR -- Type of the pattern -> HsConPatDetails GhcRn -> TcM a -> TcM (Pat GhcTc, a) tcConPat penv con_lname@(L _ con_name) pat_ty arg_pats thing_inside@@ -881,7 +883,7 @@ } tcDataConPat :: PatEnv -> LocatedN Name -> DataCon- -> Scaled ExpSigmaType -- Type of the pattern+ -> Scaled ExpSigmaTypeFRR -- Type of the pattern -> HsConPatDetails GhcRn -> TcM a -> TcM (Pat GhcTc, a) tcDataConPat penv (L con_span con_name) data_con pat_ty_scaled@@ -925,15 +927,28 @@ pat_mult = scaledMult pat_ty_scaled arg_tys_scaled = map (scaleScaled pat_mult) arg_tys' - ; traceTc "tcConPat" (vcat [ ppr con_name- , pprTyVars univ_tvs- , pprTyVars ex_tvs- , ppr eq_spec- , ppr theta- , pprTyVars ex_tvs'- , ppr ctxt_res_tys- , ppr arg_tys'- , ppr arg_pats ])+ -- This check is necessary to uphold the invariant that 'tcConArgs'+ -- is given argument types with a fixed runtime representation.+ -- See test case T20363.+ ; zipWithM_+ ( \ i arg_sty ->+ hasFixedRuntimeRep_MustBeRefl+ (FRRDataConArg Pattern data_con i)+ (scaledThing arg_sty)+ )+ [1..]+ arg_tys'++ ; traceTc "tcConPat" (vcat [ text "con_name:" <+> ppr con_name+ , text "univ_tvs:" <+> pprTyVars univ_tvs+ , text "ex_tvs:" <+> pprTyVars ex_tvs+ , text "eq_spec:" <+> ppr eq_spec+ , text "theta:" <+> ppr theta+ , text "ex_tvs':" <+> pprTyVars ex_tvs'+ , text "ctxt_res_tys:" <+> ppr ctxt_res_tys+ , text "pat_ty:" <+> ppr pat_ty+ , text "arg_tys':" <+> ppr arg_tys'+ , text "arg_pats" <+> ppr arg_pats ]) ; if null ex_tvs && null eq_spec && null theta then do { -- The common case; no class bindings etc -- (see Note [Arrows and patterns])@@ -979,7 +994,7 @@ } } tcPatSynPat :: PatEnv -> LocatedN Name -> PatSyn- -> Scaled ExpSigmaType -- Type of the pattern+ -> Scaled ExpSigmaType -- ^ Type of the pattern -> HsConPatDetails GhcRn -> TcM a -> TcM (Pat GhcTc, a) tcPatSynPat penv (L con_span con_name) pat_syn pat_ty arg_pats thing_inside@@ -1028,6 +1043,18 @@ -- see Note [Call-stack tracing of pattern synonyms] ; traceTc "instCall" (ppr req_wrap) + -- Pattern synonyms can never have representation-polymorphic argument types,+ -- as checked in 'GHC.Tc.Gen.Sig.tcPatSynSig' (see use of 'FixedRuntimeRepPatSynSigArg').+ -- (If you want to lift this restriction, use 'hasFixedRuntimeRep' here, to match+ -- 'tcDataConPat'.)+ ; let+ bad_arg_tys :: [(Int, Scaled Type)]+ bad_arg_tys = filter (\ (_, Scaled _ arg_ty) -> typeLevity_maybe arg_ty == Nothing)+ $ zip [0..] arg_tys'+ ; massertPpr (null bad_arg_tys) $+ vcat [ text "tcPatSynPat: pattern arguments do not have a fixed RuntimeRep"+ , text "bad_arg_tys:" <+> ppr bad_arg_tys ]+ ; traceTc "checkConstraints {" Outputable.empty ; (ev_binds, (arg_pats', res)) <- checkConstraints (getSkolemInfo skol_info) ex_tvs' prov_dicts' $@@ -1073,7 +1100,7 @@ ---------------------------- -- | Convenient wrapper for calling a matchExpectedXXX function matchExpectedPatTy :: (TcRhoType -> TcM (TcCoercionN, a))- -> PatEnv -> ExpSigmaType -> TcM (HsWrapper, a)+ -> PatEnv -> ExpSigmaTypeFRR -> TcM (HsWrapper, a) -- See Note [Matching polytyped patterns] -- Returns a wrapper : pat_ty ~R inner_ty matchExpectedPatTy inner_match (PE { pe_orig = orig }) pat_ty@@ -1085,13 +1112,14 @@ ---------------------------- matchExpectedConTy :: PatEnv- -> TyCon -- The TyCon that this data- -- constructor actually returns- -- In the case of a data family this is- -- the /representation/ TyCon- -> Scaled ExpSigmaType -- The type of the pattern; in the- -- case of a data family this would- -- mention the /family/ TyCon+ -> TyCon+ -- ^ The TyCon that this data constructor actually returns.+ -- In the case of a data family, this is+ -- the /representation/ TyCon.+ -> Scaled ExpSigmaTypeFRR+ -- ^ The type of the pattern.+ -- In the case of a data family, this would+ -- mention the /family/ TyCon -> TcM (HsWrapper, [TcSigmaType]) -- See Note [Matching constructor patterns] -- Returns a wrapper : pat_ty "->" T ty1 ... tyn@@ -1212,7 +1240,7 @@ -} tcConArgs :: ConLike- -> [Scaled TcSigmaType]+ -> [Scaled TcSigmaTypeFRR] -> TCvSubst -- Instantiating substitution for constructor type -> Checker (HsConPatDetails GhcRn) (HsConPatDetails GhcTc) tcConArgs con_like arg_tys tenv penv con_args thing_inside = case con_args of
compiler/GHC/Tc/Gen/Rule.hs view
@@ -397,24 +397,21 @@ -- NB: This consumes all simple constraints on the LHS, but not -- any LHS implication constraints. simplifyRule name tc_lvl lhs_wanted rhs_wanted- = do { setTcLevel tc_lvl $- do { -- Note [The SimplifyRule Plan] step 1- -- First solve the LHS and *then* solve the RHS- -- Crucially, this performs unifications- -- Why clone? See Note [Simplify cloned constraints]- -- This must be in the bumped TcLevel because cloneWC creates- -- metavariables for Concrete# constraints. See Note [The Concrete mechanism]- -- in GHC.Tc.Utils.Concrete- ; lhs_clone <- cloneWC lhs_wanted- ; rhs_clone <- cloneWC rhs_wanted- ; discardResult $- runTcS $- do {- ; _ <- solveWanteds lhs_clone- ; _ <- solveWanteds rhs_clone- -- Why do them separately?- -- See Note [Solve order for RULES]- ; return () }}+ = do {+ -- Note [The SimplifyRule Plan] step 1+ -- First solve the LHS and *then* solve the RHS+ -- Crucially, this performs unifications+ -- Why clone? See Note [Simplify cloned constraints]+ ; lhs_clone <- cloneWC lhs_wanted+ ; rhs_clone <- cloneWC rhs_wanted+ ; setTcLevel tc_lvl $+ discardResult $+ runTcS $+ do { _ <- solveWanteds lhs_clone+ ; _ <- solveWanteds rhs_clone+ -- Why do them separately?+ -- See Note [Solve order for RULES]+ ; return () } -- Note [The SimplifyRule Plan] step 2 ; lhs_wanted <- zonkWC lhs_wanted@@ -443,6 +440,7 @@ do { ev_id <- newEvVar pred ; fillCoercionHole hole (mkTcCoVarCo ev_id) ; return ev_id }+ NoDest -> pprPanic "mk_quant_ev: NoDest" (ppr ct) mk_quant_ev ct = pprPanic "mk_quant_ev" (ppr ct) @@ -489,10 +487,8 @@ | not (ok_eq t1 t2) -> False -- Note [RULE quantification over equalities] SpecialPred {}- -- RULES must never quantify over special predicates, as that- -- would leak internal GHC implementation details to the user.- --- -- Tests (for Concrete# predicates): RepPolyRule{1,2,3}.+ -- Rules should not quantify over special predicates, as these+ -- are a GHC implementation detail. -> False _ -> tyCoVarsOfCt ct `disjointVarSet` skol_tvs
compiler/GHC/Tc/Gen/Splice.hs view
@@ -10,6 +10,7 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}+{-# LANGUAGE NamedFieldPuns #-} {- (c) The University of Glasgow 2006@@ -110,6 +111,7 @@ import GHC.Types.Fixity as Hs import GHC.Types.Annotations import GHC.Types.Name+import GHC.Types.Unique.Map import GHC.Serialized import GHC.Unit.Finder@@ -154,6 +156,9 @@ import Data.Typeable ( typeOf, Typeable, TypeRep, typeRep ) import Data.Data (Data) import Data.Proxy ( Proxy (..) )+import GHC.Parser.HaddockLex (lexHsDoc)+import GHC.Parser (parseIdentifier)+import GHC.Rename.Doc (rnHsDoc) {- ************************************************************************@@ -163,8 +168,8 @@ ************************************************************************ -} -tcTypedBracket :: HsExpr GhcRn -> HsBracket GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)-tcUntypedBracket :: HsExpr GhcRn -> HsBracket GhcRn -> [PendingRnSplice] -> ExpRhoType+tcTypedBracket :: HsExpr GhcRn -> LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)+tcUntypedBracket :: HsExpr GhcRn -> HsQuote GhcRn -> [PendingRnSplice] -> ExpRhoType -> TcM (HsExpr GhcTc) tcSpliceExpr :: HsSplice GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc) -- None of these functions add constraints to the LIE@@ -184,9 +189,8 @@ -} -- See Note [How brackets and nested splices are handled]--- tcTypedBracket :: HsBracket Name -> TcRhoType -> TcM (HsExpr TcId)-tcTypedBracket rn_expr brack@(TExpBr _ expr) res_ty- = addErrCtxt (quotationCtxtDoc brack) $+tcTypedBracket rn_expr expr res_ty+ = addErrCtxt (quotationCtxtDoc expr) $ do { cur_stage <- getStage ; ps_ref <- newMutVar [] ; lie_var <- getConstraintVar -- Any constraints arising from nested splices@@ -200,29 +204,27 @@ -- Bundle them together so they can be used in GHC.HsToCore.Quote for desugaring -- brackets. ; let wrapper = QuoteWrapper ev_var m_var- -- Typecheck expr to make sure it is valid,- -- Throw away the typechecked expression but return its type.+ -- Typecheck expr to make sure it is valid.+ -- The typechecked expression won't be used, but we return it with its type.+ -- (See Note [The life cycle of a TH quotation] in GHC.Hs.Expr) -- We'll typecheck it again when we splice it in somewhere- ; (_tc_expr, expr_ty) <- setStage (Brack cur_stage (TcPending ps_ref lie_var wrapper)) $- tcScalingUsage Many $- -- Scale by Many, TH lifting is currently nonlinear (#18465)- tcInferRhoNC expr- -- NC for no context; tcBracket does that+ ; (tc_expr, expr_ty) <- setStage (Brack cur_stage (TcPending ps_ref lie_var wrapper)) $+ tcScalingUsage Many $+ -- Scale by Many, TH lifting is currently nonlinear (#18465)+ tcInferRhoNC expr+ -- NC for no context; tcBracket does that ; let rep = getRuntimeRep expr_ty ; meta_ty <- tcTExpTy m_var expr_ty ; ps' <- readMutVar ps_ref ; codeco <- tcLookupId unsafeCodeCoerceName ; bracket_ty <- mkAppTy m_var <$> tcMetaTy expTyConName- ; tcWrapResultO (Shouldn'tHappenOrigin "TExpBr")+ ; tcWrapResultO (Shouldn'tHappenOrigin "TH typed bracket expression") rn_expr (unLoc (mkHsApp (mkLHsWrap (applyQuoteWrapper wrapper) (nlHsTyApp codeco [rep, expr_ty]))- (noLocA (HsTcBracketOut bracket_ty (Just wrapper) brack ps'))))+ (noLocA (HsTypedBracket (HsBracketTc (ExpBr noExtField expr) bracket_ty (Just wrapper) ps') tc_expr)))) meta_ty res_ty }-tcTypedBracket _ other_brack _- = pprPanic "tcTypedBracket" (ppr other_brack) --- tcUntypedBracket :: HsBracket Name -> [PendingRnSplice] -> ExpRhoType -> TcM (HsExpr TcId) -- See Note [Typechecking Overloaded Quotes] tcUntypedBracket rn_expr brack ps res_ty = do { traceTc "tc_bracket untyped" (ppr brack $$ ppr ps)@@ -246,7 +248,8 @@ -- Unify the overall type of the bracket with the expected result -- type ; tcWrapResultO BracketOrigin rn_expr- (HsTcBracketOut expected_type brack_info brack ps')+ (HsUntypedBracket (HsBracketTc brack expected_type brack_info ps') (XQuote noExtField))+ -- (XQuote noExtField): see Note [The life cycle of a TH quotation] in GHC.Hs.Expr expected_type res_ty }@@ -268,7 +271,7 @@ -- | Compute the expected type of a quotation, and also the QuoteWrapper in -- the case where it is an overloaded quotation. All quotation forms are -- overloaded aprt from Variable quotations ('foo)-brackTy :: HsBracket GhcRn -> TcM (Maybe QuoteWrapper, Type)+brackTy :: HsQuote GhcRn -> TcM (Maybe QuoteWrapper, Type) brackTy b = let mkTy n = do -- New polymorphic type variable for the bracket@@ -291,7 +294,6 @@ (DecBrG {}) -> mkTy decsTyConName -- Result type is m [Dec] (PatBr {}) -> mkTy patTyConName -- Result type is m Pat (DecBrL {}) -> panic "tcBrackTy: Unexpected DecBrL"- (TExpBr {}) -> panic "tcUntypedBracket: Unexpected TExpBr" --------------- -- | Typechecking a pending splice from a untyped bracket@@ -329,10 +331,10 @@ , text "The type of a Typed Template Haskell expression must" <+> text "not have any quantification." ] -quotationCtxtDoc :: HsBracket GhcRn -> SDoc+quotationCtxtDoc :: LHsExpr GhcRn -> SDoc quotationCtxtDoc br_body = hang (text "In the Template Haskell quotation")- 2 (ppr br_body)+ 2 (thTyBrackets . ppr $ br_body) -- The whole of the rest of the file is the else-branch (ie stage2 only)@@ -366,43 +368,46 @@ and untyped [| e |] The life cycle of a typed bracket:- * Starts as HsBracket+ * Starts as HsTypedBracket * When renaming: * Set the ThStage to (Brack s RnPendingTyped) * Rename the body- * Result is still a HsBracket+ * Result is a HsTypedBracket * When typechecking: * Set the ThStage to (Brack s (TcPending ps_var lie_var))- * Typecheck the body, and throw away the elaborated result+ * Typecheck the body, and keep the elaborated result (despite never using it!) * Nested splices (which must be typed) are typechecked, and the results accumulated in ps_var; their constraints accumulate in lie_var- * Result is a HsTcBracketOut rn_brack pending_splices- where rn_brack is the incoming renamed bracket+ * Result is a HsTypedBracket (HsBracketTc rn_brack ty quote_wrapper pending_splices) tc_brack+ where rn_brack is the untyped renamed exp quote constructed from the typed renamed expression :: HsQuote GhcRn The life cycle of a un-typed bracket:- * Starts as HsBracket+ * Starts as HsUntypedBracket * When renaming: * Set the ThStage to (Brack s (RnPendingUntyped ps_var)) * Rename the body * Nested splices (which must be untyped) are renamed, and the results accumulated in ps_var- * Result is still (HsRnBracketOut rn_body pending_splices)+ * Result is a HsUntypedBracket pending_splices rn_body - * When typechecking a HsRnBracketOut+ * When typechecking: * Typecheck the pending_splices individually * Ignore the body of the bracket; just check that the context expects a bracket of that type (e.g. a [p| pat |] bracket should be in a context needing a (Q Pat)- * Result is a HsTcBracketOut rn_brack pending_splices- where rn_brack is the incoming renamed bracket+ * Result is a HsUntypedBracket (HsBracketTc rn_brack ty quote_wrapper pending_splices) (XQuote noExtField)+ where rn_brack is the incoming renamed bracket :: HsQuote GhcRn+ and (XQuote noExtField) stands for the removal of the `HsQuote GhcTc` field (since `HsQuote GhcTc` isn't possible) +See the related Note [The life cycle of a TH quotation] In both cases, desugaring happens like this:- * HsTcBracketOut is desugared by GHC.HsToCore.Quote.dsBracket. It+ * Hs*Bracket is desugared by GHC.HsToCore.Quote.dsBracket using the renamed+ expression held in `HsBracketTc` (`type instance X*Bracket GhcTc = HsBracketTc`). It a) Extends the ds_meta environment with the PendingSplices attached to the bracket@@ -424,11 +429,11 @@ Example: Source: f = [| Just $(g 3) |]- The [| |] part is a HsBracket+ The [| |] part is a HsUntypedBracket GhcPs Typechecked: f = [| Just ${s7}(g 3) |]{s7 = g Int 3}- The [| |] part is a HsBracketOut, containing *renamed*- (not typechecked) expression+ The [| |] part is a HsUntypedBracket GhcTc, containing *renamed*+ (not typechecked) expression (see Note [The life cycle of a TH quotation]) The "s7" is the "splice point"; the (g Int 3) part is a typechecked expression @@ -1307,7 +1312,10 @@ unless is_local $ failWithTc $ TcRnUnknownMessage $ mkPlainError noHints $ text "Can't add documentation to" <+> ppr_loc doc_loc <+> text "as it isn't inside the current module"- updTcRef th_doc_var (Map.insert resolved_doc_loc s)+ let ds = mkGeneratedHsDocString s+ hd = lexHsDoc parseIdentifier ds+ hd' <- rnHsDoc hd+ updTcRef th_doc_var (Map.insert resolved_doc_loc hd') where resolve_loc (TH.DeclDoc n) = DeclDoc <$> lookupThName n resolve_loc (TH.ArgDoc n i) = ArgDoc <$> lookupThName n <*> pure i@@ -1331,40 +1339,41 @@ qGetDoc (TH.InstDoc t) = lookupThInstName t >>= lookupDeclDoc qGetDoc (TH.ArgDoc n i) = lookupThName n >>= lookupArgDoc i qGetDoc TH.ModuleDoc = do- (moduleDoc, _, _) <- getGblEnv >>= extractDocs- return (fmap unpackHDS moduleDoc)+ df <- getDynFlags+ docs <- getGblEnv >>= extractDocs df+ return (renderHsDocString . hsDocString <$> (docs_mod_hdr =<< docs)) -- | Looks up documentation for a declaration in first the current module, -- otherwise tries to find it in another module via 'hscGetModuleInterface'. lookupDeclDoc :: Name -> TcM (Maybe String) lookupDeclDoc nm = do- (_, DeclDocMap declDocs, _) <- getGblEnv >>= extractDocs- fam_insts <- tcg_fam_insts <$> getGblEnv- traceTc "lookupDeclDoc" (ppr nm <+> ppr declDocs <+> ppr fam_insts)- case Map.lookup nm declDocs of- Just doc -> pure $ Just (unpackHDS doc)+ df <- getDynFlags+ Docs{docs_decls} <- fmap (fromMaybe emptyDocs) $ getGblEnv >>= extractDocs df+ case lookupUniqMap docs_decls nm of+ Just doc -> pure $ Just (renderHsDocStrings $ map hsDocString doc) Nothing -> do -- Wasn't in the current module. Try searching other external ones! mIface <- getExternalModIface nm case mIface of- Nothing -> pure Nothing- Just ModIface { mi_decl_docs = DeclDocMap dmap } ->- pure $ unpackHDS <$> Map.lookup nm dmap+ Just ModIface { mi_docs = Just Docs{docs_decls = dmap} } ->+ pure $ renderHsDocStrings . map hsDocString <$> lookupUniqMap dmap nm+ _ -> pure Nothing -- | Like 'lookupDeclDoc', looks up documentation for a function argument. If -- it can't find any documentation for a function in this module, it tries to -- find it in another module. lookupArgDoc :: Int -> Name -> TcM (Maybe String) lookupArgDoc i nm = do- (_, _, ArgDocMap argDocs) <- getGblEnv >>= extractDocs- case Map.lookup nm argDocs of- Just m -> pure $ unpackHDS <$> IntMap.lookup i m+ df <- getDynFlags+ Docs{docs_args = argDocs} <- fmap (fromMaybe emptyDocs) $ getGblEnv >>= extractDocs df+ case lookupUniqMap argDocs nm of+ Just m -> pure $ renderHsDocString . hsDocString <$> IntMap.lookup i m Nothing -> do mIface <- getExternalModIface nm case mIface of- Nothing -> pure Nothing- Just ModIface { mi_arg_docs = ArgDocMap amap } ->- pure $ unpackHDS <$> (Map.lookup nm amap >>= IntMap.lookup i)+ Just ModIface { mi_docs = Just Docs{docs_args = amap} } ->+ pure $ renderHsDocString . hsDocString <$> (lookupUniqMap amap nm >>= IntMap.lookup i)+ _ -> pure Nothing -- | Returns the module a Name belongs to, if it is isn't local. getExternalModIface :: Name -> TcM (Maybe ModIface)@@ -1395,7 +1404,7 @@ <+> ppr_th th_type <+> text "to add documentation to" - -- | Get the name of the class for the instance we are documenting+ -- Get the name of the class for the instance we are documenting -- > inst_cls_name (Monad Maybe) == Monad -- > inst_cls_name C = C inst_cls_name :: TH.Type -> TcM TH.Name@@ -1434,7 +1443,7 @@ <+> ppr_th th_type <+> text "is supposed to be" - -- | Basically does the opposite of 'mkThAppTs'+ -- Basically does the opposite of 'mkThAppTs' -- > inst_arg_types (Monad Maybe) == [Maybe] -- > inst_arg_types C == [] inst_arg_types :: TH.Type -> [TH.Type]
compiler/GHC/Tc/Gen/Splice.hs-boot view
@@ -10,23 +10,23 @@ import GHC.Types.Annotations ( Annotation, CoreAnnTarget ) import GHC.Hs.Extension ( GhcRn, GhcPs, GhcTc ) -import GHC.Hs ( HsSplice, HsBracket, HsExpr, LHsExpr, LHsType, LPat,- LHsDecl, ThModFinalizers )+import GHC.Hs ( HsSplice, HsQuote, HsExpr, LHsExpr, LHsType,+ LPat, LHsDecl, ThModFinalizers ) import qualified Language.Haskell.TH as TH tcSpliceExpr :: HsSplice GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc) +tcTypedBracket :: HsExpr GhcRn+ -> LHsExpr GhcRn+ -> ExpRhoType+ -> TcM (HsExpr GhcTc) tcUntypedBracket :: HsExpr GhcRn- -> HsBracket GhcRn+ -> HsQuote GhcRn -> [PendingRnSplice] -> ExpRhoType -> TcM (HsExpr GhcTc)-tcTypedBracket :: HsExpr GhcRn- -> HsBracket GhcRn- -> ExpRhoType- -> TcM (HsExpr GhcTc) runTopSplice :: DelayedSplice -> TcM (HsExpr GhcTc)
compiler/GHC/Tc/Module.hs view
@@ -95,6 +95,7 @@ import GHC.Rename.Names import GHC.Rename.Env import GHC.Rename.Module+import GHC.Rename.Doc import GHC.Iface.Syntax ( ShowSub(..), showToHeader ) import GHC.Iface.Type ( ShowForAllFlag(..) )@@ -292,22 +293,23 @@ tcg_env <- {-# SCC "tcRnImports" #-} tcRnImports hsc_env all_imports - ; -- Don't need to rename the Haddock documentation,- -- it's not parsed by GHC anymore.- -- Make sure to do this before 'tcRnSrcDecls', because we need the- -- module header when we're splicing TH, since it can be accessed via- -- 'getDoc'.- tcg_env <- return (tcg_env- { tcg_doc_hdr = maybe_doc_hdr })-+ -- Put a version of the header without identifier info into the tcg_env+ -- Make sure to do this before 'tcRnSrcDecls', because we need the+ -- module header when we're splicing TH, since it can be accessed via+ -- 'getDoc'.+ -- We will rename it properly after renaming everything else so that+ -- haddock can link the identifiers+ ; tcg_env <- return (tcg_env+ { tcg_doc_hdr = fmap (\(WithHsDocIdentifiers str _) -> WithHsDocIdentifiers str [])+ <$> maybe_doc_hdr }) ; -- If the whole module is warned about or deprecated -- (via mod_deprec) record that in tcg_warns. If we do thereby add -- a WarnAll, it will override any subsequent deprecations added to tcg_warns- let { tcg_env1 = case mod_deprec of- Just (L _ txt) ->- tcg_env {tcg_warns = WarnAll txt}- Nothing -> tcg_env- }+ ; tcg_env1 <- case mod_deprec of+ Just (L _ txt) -> do { txt' <- rnWarningTxt txt+ ; pure $ tcg_env {tcg_warns = WarnAll txt'}+ }+ Nothing -> pure tcg_env ; setGblEnv tcg_env1 $ do { -- Rename and type check the declarations traceRn "rn1a" empty@@ -337,11 +339,17 @@ -- because the latter might add new bindings for -- boot_dfuns, which may be mentioned in imported -- unfoldings.- -- Report unused names+ ; -- Report unused names -- Do this /after/ typeinference, so that when reporting -- a function with no type signature we can give the -- inferred type- reportUnusedNames tcg_env hsc_src+ ; reportUnusedNames tcg_env hsc_src++ -- Rename the module header properly after we have renamed everything else+ ; maybe_doc_hdr <- traverse rnLHsDoc maybe_doc_hdr;+ ; tcg_env <- return (tcg_env+ { tcg_doc_hdr = maybe_doc_hdr })+ ; -- add extra source files to tcg_dependent_files addDependentFiles src_files -- Ensure plugins run with the same tcg_env that we pass in@@ -1276,7 +1284,7 @@ -- -- See also 'HowAbstract' and Note [Skolem abstract data]. - -- | Given @type T tvs = ty@, where @ty@ decomposes into @tc2' args@,+ -- Given @type T tvs = ty@, where @ty@ decomposes into @tc2' args@, -- check that this synonym is an acceptable implementation of @tc1@. -- See Note [Synonyms implement abstract data] checkSynAbsData :: [TyVar] -> Type -> TyCon -> [Type] -> Maybe SDoc@@ -1707,9 +1715,9 @@ }} where -- Check whether the desired superclass exists in a given environment.- checkShouldInst :: Class -- ^ Class of existing instance- -> Class -- ^ Class there should be an instance of- -> ClsInst -- ^ Existing instance+ checkShouldInst :: Class -- Class of existing instance+ -> Class -- Class there should be an instance of+ -> ClsInst -- Existing instance -> TcM () checkShouldInst isClass shouldClass isInst = do { instEnv <- tcGetInstEnvs@@ -2167,7 +2175,7 @@ -- None of the Ids should be of unboxed type, because we -- cast them all to HValues in the end!- mapM_ bad_unboxed (filter (isUnliftedType . idType) zonked_ids) ;+ mapM_ bad_unboxed (filter (mightBeUnliftedType . idType) zonked_ids) ; traceTc "tcs 1" empty ; this_mod <- getModule ;@@ -2233,6 +2241,9 @@ -- An expression typed at the prompt is treated very specially tcUserStmt (L loc (BodyStmt _ expr _ _)) = do { (rn_expr, fvs) <- checkNoErrs (rnLExpr expr)++ ; dumpOptTcRn Opt_D_dump_rn_ast "Renamer" FormatHaskell+ (showAstData NoBlankSrcSpan NoBlankEpAnnotations rn_expr) -- Don't try to typecheck if the renamer fails! ; ghciStep <- getGhciStepIO ; uniq <- newUnique@@ -2329,6 +2340,9 @@ then no_it_plans else it_plans + ; dumpOptTcRn Opt_D_dump_tc_ast "Typechecker AST" FormatHaskell+ (showAstData NoBlankSrcSpan NoBlankEpAnnotations plan)+ ; fix_env <- getFixityEnv ; return (plan, fix_env) } @@ -2467,8 +2481,8 @@ ; traceTc "GHC.Tc.Module.tcGhciStmts: done" empty - -- rec_expr is the expression- -- returnIO @ [()] [unsafeCoerce# () x, .., unsafeCorece# () z]+ -- ret_expr is the expression+ -- returnIO @[()] [unsafeCoerce# () x, .., unsafeCoerce# () z] -- -- Despite the inconvenience of building the type applications etc, -- this *has* to be done in type-annotated post-typecheck form@@ -3174,7 +3188,7 @@ -- exception/signal an error. type RenamedStuff = (Maybe (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)],- Maybe LHsDocString))+ Maybe (LHsDoc GhcRn))) -- | Extract the renamed information from TcGblEnv. getRenamedStuff :: TcGblEnv -> RenamedStuff
compiler/GHC/Tc/Solver.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE RecursiveDo #-}-{-# LANGUAGE MultiWayIf #-} module GHC.Tc.Solver( InferMode(..), simplifyInfer, findInferredDiff,@@ -1193,7 +1192,7 @@ -------------------- emitResidualConstraints :: TcLevel -> EvBindsVar -> [(Name, TcTauType)]- -> VarSet -> [TcTyVar] -> [EvVar]+ -> CoVarSet -> [TcTyVar] -> [EvVar] -> WantedConstraints -> TcM () -- Emit the remaining constraints from the RHS. emitResidualConstraints rhs_tclvl ev_binds_var@@ -1204,7 +1203,11 @@ | otherwise = do { wanted_simple <- TcM.zonkSimples (wc_simple wanteds) ; let (outer_simple, inner_simple) = partitionBag is_mono wanted_simple- is_mono ct = isWantedCt ct && ctEvId ct `elemVarSet` co_vars+ is_mono ct+ | Just ct_ev_id <- wantedEvId_maybe ct+ = ct_ev_id `elemVarSet` co_vars+ | otherwise+ = False -- Reason for the partition: -- see Note [Emitting the residual implication in simplifyInfer] @@ -1561,7 +1564,7 @@ -> [PredType] -- Candidate theta; already zonked -> TcM ( [TcTyVar] -- Quantify over these (skolems) , [PredType] -- and this context (fully zonked)- , VarSet)+ , CoVarSet) -- See Note [Deciding quantification] decideQuantification skol_info infer_mode rhs_tclvl name_taus psigs candidates = do { -- Step 1: find the mono_tvs@@ -1810,11 +1813,9 @@ simplify_cand [] = return [] -- see Note [Unconditionally resimplify constraints when quantifying] simplify_cand candidates- = do { WC { wc_simple = simples } <- setTcLevel rhs_tclvl $- do { wanteds <- newWanteds DefaultOrigin candidates- -- build wanteds at bumped level because newConcreteHole- -- whips up fresh metavariables- ; simplifyWantedsTcM wanteds }+ = do { clone_wanteds <- newWanteds DefaultOrigin candidates+ ; WC { wc_simple = simples } <- setTcLevel rhs_tclvl $+ simplifyWantedsTcM clone_wanteds -- Discard evidence; simples is fully zonked ; let new_candidates = ctsPreds simples
compiler/GHC/Tc/Solver/Canonical.hs view
@@ -15,7 +15,6 @@ import GHC.Tc.Types.Constraint import GHC.Core.Predicate import GHC.Tc.Types.Origin-import GHC.Tc.Utils.Concrete ( newConcretePrimWanted ) import GHC.Tc.Utils.Unify import GHC.Tc.Utils.TcType import GHC.Core.Type@@ -43,7 +42,6 @@ import GHC.Utils.Panic import GHC.Utils.Panic.Plain import GHC.Builtin.Types ( anyTypeOfKind )-import GHC.Builtin.Types.Prim ( concretePrimTyCon ) import GHC.Types.Name.Set import GHC.Types.Name.Reader import GHC.Hs.Type( HsIPName(..) )@@ -62,7 +60,6 @@ import qualified Data.Semigroup as S import Data.Bifunctor ( bimap ) import Data.Foldable ( traverse_ )-import GHC.Tc.Utils.Monad (setTcLevel) {- ************************************************************************@@ -104,9 +101,6 @@ canonicalize (CQuantCan (QCI { qci_ev = ev, qci_pend_sc = pend_sc })) = canForAll ev pend_sc -canonicalize (CSpecialCan { cc_ev = ev, cc_special_pred = special_pred, cc_xi = xi })- = canSpecial ev special_pred xi- canonicalize (CIrredCan { cc_ev = ev }) = canNC ev -- Instead of rewriting the evidence before classifying, it's possible we@@ -130,6 +124,9 @@ = {-# SCC "canEqLeafTyVarEq" #-} canEqNC ev eq_rel (canEqLHSType lhs) rhs +canonicalize (CSpecialCan { cc_ev = ev, cc_special_pred = special_pred })+ = canSpecial ev special_pred+ canNC :: CtEvidence -> TcS (StopOrContinue Ct) canNC ev = case classifyPredType pred of@@ -141,8 +138,9 @@ canIrred ev ForAllPred tvs th p -> do traceTcS "canEvNC:forall" (ppr pred) canForAllNC ev tvs th p- SpecialPred tc ty -> do traceTcS "canEvNC:special" (ppr pred)- canSpecial ev tc ty+ SpecialPred spec -> do traceTcS "canEvNC:special" (ppr pred)+ canSpecial ev spec+ where pred = ctEvPred ev @@ -546,6 +544,8 @@ do_one_given sel_id | isUnliftedType sc_pred+ -- NB: class superclasses are never representation-polymorphic,+ -- so isUnliftedType is OK here. , not (null tvs && null theta) = -- See Note [Equality superclasses in quantified constraints] return []@@ -750,10 +750,9 @@ -- in with a polytype. This is #18987. do traceTcS "canEvNC:forall" (ppr pred) canForAllNC ev tvs th p- SpecialPred tc tys -> -- IrredPreds have kind Constraint, so cannot+ SpecialPred {} -> -- IrredPreds have kind Constraint, so cannot -- become SpecialPreds- pprPanic "canIrred: SpecialPred"- (ppr ev $$ ppr tc $$ ppr tys)+ pprPanic "canIrred: SpecialPred" (ppr ev) IrredPred {} -> continueWith $ mkIrredCt IrredShapeReason new_ev } } @@ -932,213 +931,39 @@ ********************************************************************* -} -- | Canonicalise a 'SpecialPred' constraint.-canSpecial :: CtEvidence -> SpecialPred -> TcType -> TcS (StopOrContinue Ct)-canSpecial ev special_pred ty- = do { -- Special constraints should never appear in Givens.- ; massertPpr (not $ isGivenOrigin $ ctEvOrigin ev)- (text "canSpecial: Given Special constraint" $$ ppr ev)- ; case special_pred of- { ConcretePrimPred -> canConcretePrim ev ty } }--{- Note [Canonical Concrete# constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-A 'Concrete#' constraint can be decomposed precisely when-it is an application, possibly nullary, of a concrete 'TyCon'.--A canonical 'Concrete#' constraint is one that cannot be decomposed.--To illustrate, when we come across a constraint of the form `Concrete# (f a_1 ... a_n)`,-to canonicalise it, we decompose it into the collection of constraints-`Concrete# a_1`, ..., `Concrete# a_n`, whenever `f` is a concrete type constructor-(that is, it is not a type variable, nor a type-family, nor an abstract 'TyCon'-as declared in a Backpack signature file).--Writing NC for a non-canonical constraint and C for a canonical one,-here are some examples:-- (1)- NC: Concrete# IntRep- ==> nullary decomposition, by observing that `IntRep = TyConApp intRepTyCon []`-- (2)- NC: Concrete# (TYPE (TupleRep '[Rep, rr])) -- where 'Rep' is an abstract type and 'rr' is a type variable- ==> decompose once, noting that 'TYPE' is a concrete 'TyCon'- NC: Concrete# (TupleRep '[Rep, rr])- ==> decompose again in the same way but with 'TupleRep'- NC: Concrete# ((:) @RuntimeRep Rep ((:) @RuntimeRep rr []))- ==> handle (:) and its type-level argument 'RuntimeRep' (which is concrete)- C: Concrete# Rep, NC: Concrete# ((:) @RuntimeRep rr []))- ==> the second constraint can be decomposed again; 'RuntimeRep' and '[]' are concrete, so we get- C: Concrete# Rep, C: Concrete# rr--Note [Solving Concrete constraints requires simplifyArgsWorker]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We have- [W] co :: Concrete# [LiftedRep, IntRep]-and wish to canonicalise it so that we can solve it. Of course, that's really- [W] co :: Concrete# ((:) @RuntimeRep LiftedRep ((:) @RuntimeRep IntRep ('[] @RuntimeRep)))--We can decompose to- [W] co1 :: Concrete# RuntimeRep- [W] co2 :: Concrete# LiftedRep- [W] co3 :: Concrete# ((:) @RuntimeRep IntRep ('[] @RuntimeRep))--Recall (Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete) that the evidence for-a Concrete# ty constraint is a coercion of type ty ~# alpha, where we require a concrete-type (one that responds True to GHC.Core.Type.isConcrete) to fill in alpha when solving-the constraint. Accordingly, when we create these new Concrete# constraints, we create-new metavariables alpha1 :: Type, alpha2 :: RuntimeRep, alpha3 :: [RuntimeRep], with:-- co1 :: RuntimeRep ~# alpha1- co2 :: LiftedRep ~# alpha2- co3 :: '[IntRep] ~# alpha3--and we already have-- co :: [LiftedRep, IntRep] ~# alpha0--We are now solving co. What do we fill in alpha0 with? The naive answer is to say-- alpha0 := (:) alpha1 alpha2 alpha3--but this would be ill-kinded! The first problem is that `(:) alpha1` expects its next-argument to have kind alpha1. (The next argument -- alpha3 -- is problematic, too.) The-second problem is that alpha0 :: [RuntimeRep], but the right-hand side above has kind-[alpha1]. Happily, we have a solution close to hand: simplifyArgsWorker, which deals-with precisely this scenario, of replacing all the arguments to a function (in this case, (:)),-with new arguments but making sure the kinds line up. All we have to do is bundle the information-we have in a form simplifyArgsWorker likes, and then do the reverse from its result.---}---- | Canonicalise a 'Concrete#' constraint.------ See Note [Canonical Concrete# constraints] for details.-canConcretePrim :: CtEvidence -> TcType -> TcS (StopOrContinue Ct)-canConcretePrim ev ty- = do {- -- As per Note [The Concrete mechanism] in GHC.Tc.Instance.Class,- -- in PHASE 1, we don't allow a 'Concrete#' constraint to be rewritten.- -- We still need to zonk, otherwise we can end up stuck with a constraint- -- such as `Concrete# rep` for a unification variable `rep`,- -- which we can't make progress on.- ; ty <- zonkTcType ty- ; traceTcS "canConcretePrim" $- vcat [text "ev =" <+> ppr ev, text "ty =" <+> ppr ty]-- ; decomposeConcretePrim ev ty }---- | Try to decompose a 'Concrete#' constraint:------ - calls 'canDecomposableConcretePrim' if the constraint can be decomposed;--- - calls 'canNonDecomposableConcretePrim' otherwise.-decomposeConcretePrim :: CtEvidence -> Type -> TcS (StopOrContinue Ct)-decomposeConcretePrim ev ty- -- Handle applications of concrete 'TyCon's.- -- See examples (1,2) in Note [Canonical Concrete# constraints].- | (f,args) <- tcSplitAppTys ty- , Just f_tc <- tyConAppTyCon_maybe f- , isConcreteTyCon f_tc- = canDecomposableConcretePrim ev f_tc args-- -- Couldn't decompose the constraint: keep it as-is.- | otherwise- = canNonDecomposableConcretePrim ev ty---- | Decompose a constraint of the form @'Concrete#' (f t_1 ... t_n)@,--- for a concrete `TyCon' `f`.------ This function will emit new Wanted @Concrete# t_i@ constraints, one for--- each of the arguments of `f`.------ See Note [Canonical Concrete# constraints].-canDecomposableConcretePrim :: CtEvidence- -> TyCon- -> [TcType]- -> TcS (StopOrContinue Ct)-canDecomposableConcretePrim ev f_tc args- = do { traceTcS "canDecomposableConcretePrim" $- vcat [text "args =" <+> ppr args, text "ev =" <+> ppr ev]- ; let ev_lvl- | CtWanted { ctev_dest = HoleDest hole } <- ev- , (_, _, _, conc_rhs_ty, Nominal) <- coVarKindsTypesRole (coHoleCoVar hole)- , Just conc_rhs_tv <- getTyVar_maybe conc_rhs_ty- , Just lvl <- metaTyVarTcLevel_maybe conc_rhs_tv- = lvl-- | otherwise- = pprPanic "canDecomposableConcretePrim" (ppr ev)-- ; (arg_cos, rhs_args)- <- mapAndUnzipM (emit_new_concretePrim_wanted ev_lvl (ctEvLoc ev)) args-- -- See Note [Solving Concrete constraints requires simplifyArgsWorker]- ; let (tc_binders, tc_res_kind) = splitPiTys (tyConKind f_tc)- fvs_args = tyCoVarsOfTypes rhs_args- ArgsReductions reductions final_co- = simplifyArgsWorker tc_binders tc_res_kind fvs_args- (repeat Nominal) (zipWith mkReduction arg_cos rhs_args)- Reduction concrete_co uncasted_concrete_rhs = mkTyConAppRedn Nominal f_tc reductions- concrete_rhs = uncasted_concrete_rhs `mkCastTyMCo` mkSymMCo final_co-- ; solveConcretePrimWanted ev concrete_co concrete_rhs- ; stopWith ev "Decomposed Concrete#" }---- | Canonicalise a non-decomposable 'Concrete#' constraint.-canNonDecomposableConcretePrim :: CtEvidence -> TcType -> TcS (StopOrContinue Ct)-canNonDecomposableConcretePrim ev ty- = do { -- Update the evidence to account for the zonk to `ty`.- let ki = typeKind ty- new_ev = setCtEvPredType ev (mkTyConApp concretePrimTyCon [ki, ty])- new_ct =- CSpecialCan { cc_ev = new_ev- , cc_special_pred = ConcretePrimPred- , cc_xi = ty }- ; traceTcS "canNonDecomposableConcretePrim" $- vcat [ text "ty =" <+> ppr ty, text "new_ev =" <+> ppr new_ev ]- ; continueWith new_ct }---- | Create a new 'Concrete#' Wanted constraint and immediately add it--- to the work list. Returns the evidence (a coercion hole) used for the--- constraint, and the right-hand type (a metavariable) of that coercion-emit_new_concretePrim_wanted :: TcLevel -> CtLoc -> Type -> TcS (Coercion, TcType)-emit_new_concretePrim_wanted ev_lvl loc ty- = do { (hole, rhs_ty, wanted) <- wrapTcS $ setTcLevel ev_lvl $ newConcretePrimWanted loc ty- ; emitWorkNC [wanted]- ; return (mkHoleCo hole, rhs_ty) }+canSpecial :: CtEvidence -> SpecialPred -> TcS (StopOrContinue Ct)+canSpecial ev special_pred =+ case special_pred of+ IsReflPrimPred lhs rhs ->+ canIsReflPrim ev lhs rhs --- | Solve a Wanted 'Concrete#' constraint.------ Recall that, when we create a Wanted constraint of the form @Concrete# ty@,--- we create a metavariable @concrete_tau@ and a coercion hole of type--- @ty ~# concrete_tau@.+-- | Canonicalise a 'IsRefl#' constraint: zonk the lhs and rhs,+-- and solve it if they are equal. ----- When we want to solve this constraint, because we have found that--- @ty@ is indeed equal to a concrete type @rhs@, we thus need to do--- two things:+-- See Note [IsRefl#] in GHC.Tc.Utils.Concrete. ----- 1. fill the metavariable @concrete_tau := rhs@,--- 2. fill the coercion hole with the evidence for the equality @ty ~# rhs@.-solveConcretePrimWanted :: HasDebugCallStack- => CtEvidence -- ^ always a [W] Concrete# ty- -> Coercion -- ^ @co :: ty ~ rhs@- -> TcType -- ^ @rhs@, which must be concrete- -> TcS ()-solveConcretePrimWanted (CtWanted { ctev_dest = dest@(HoleDest hole) }) co rhs- = do { let Pair _ty concrete_tau = coVarTypes $ coHoleCoVar hole- tau_tv = getTyVar "solveConcretePrimWanted" concrete_tau- ; unifyTyVar tau_tv rhs- ; setWantedEq dest co }--solveConcretePrimWanted ev co rhs- = pprPanic "solveConcretePrimWanted: no coercion hole to fill" $- vcat [ text "ev =" <+> ppr ev <> semi <+> text "dest =" <+> case ev of- CtWanted { ctev_dest = EvVarDest var } -> text "var" <+> ppr var- _ -> text "XXX NOT EVEN A WANTED XXX"- , text "co =" <+> ppr co- , text "rhs =" <+> ppr rhs ]+-- Important: we never rewrite the arguments to an 'IsRefl#' constraint+-- (we only zonk them), as rewriting would defeat the whole purpose of the constraint!+canIsReflPrim :: CtEvidence -> TcType -> TcType -> TcS (StopOrContinue Ct)+canIsReflPrim ev lhs rhs+ = do { -- IsRefl# constraints should never appear in Givens.+ ; massertPpr (not $ isGivenOrigin $ ctEvOrigin ev)+ (text "canIsReflPrim: Given IsRefl# constraint" $$ ppr ev)+ ; lhs <- zonkTcType lhs+ ; rhs <- zonkTcType rhs+ ; if lhs `tcEqType` rhs+ then stopWith ev "Solved IsRefl#"+ else+ do { let new_pty = mkIsReflPrimPred lhs rhs+ new_ev = setCtEvPredType ev new_pty+ new_ct = CSpecialCan { cc_ev = new_ev+ , cc_special_pred = IsReflPrimPred lhs rhs }+ ; traceTcS "canIsReflPrim continueWith" $+ vcat [ text "new_ev =" <+> ppr new_ev+ , text "lhs =" <+> ppr lhs, text "rhs =" <+> ppr rhs ]+ ; continueWith new_ct }} -{- **********************************************************************+{-********************************************************************** * * * Equalities * *
compiler/GHC/Tc/Solver/Interact.hs view
@@ -429,7 +429,9 @@ CEqCan {} -> interactEq ics wi CIrredCan {} -> interactIrred ics wi CDictCan {} -> interactDict ics wi- CSpecialCan {} -> continueWith wi -- cannot have Special Givens, so nothing to interact with+ CSpecialCan { cc_special_pred = spec } ->+ case spec of+ IsReflPrimPred {} -> continueWith wi -- cannot have IsRefl# Givens, so nothing to interact with _ -> pprPanic "interactWithInerts" (ppr wi) } -- CNonCanonical have been canonicalised @@ -1891,13 +1893,14 @@ CEqCan {} -> doTopReactEq work_item - CSpecialCan {} ->- -- No top-level interactions for special constraints.- continueWith work_item- CIrredCan {} -> doTopReactOther work_item + CSpecialCan { cc_special_pred = spec } ->+ case spec of+ IsReflPrimPred {} -> continueWith work_item+ -- No top-level interactions for IsRefl# constraints.+ -- Any other work item does not react with any top-level equations _ -> continueWith work_item } @@ -2349,7 +2352,7 @@ - natural numbers - Typeable -* See also Note [What might equal later?] in GHC.Tc.Solver.Monad.+* See also Note [What might equal later?] in GHC.Tc.Solver.InertSet. * The given-overlap problem is arguably not easy to appear in practice due to our aggressive prioritization of equality solving over other
compiler/GHC/Tc/Solver/Monad.hs view
@@ -8,7 +8,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} -{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}+{-# OPTIONS_GHC -Wno-incomplete-record-updates -Wno-orphans #-} -- | Monadic definitions for the constraint solver module GHC.Tc.Solver.Monad (@@ -168,7 +168,6 @@ import GHC.Tc.Utils.Unify import GHC.Core.Predicate import GHC.Types.Unique.Set (nonDetEltsUniqSet)-import GHC.Utils.Panic.Plain import Control.Monad import GHC.Utils.Monad@@ -632,92 +631,6 @@ insoluble_given_equality ct = insolubleEqCt ct && isGivenCt ct -{- Note [What might equal later?]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We must determine whether a Given might later equal a Wanted. We-definitely need to account for the possibility that any metavariable-might be arbitrarily instantiated. Yet we do *not* want-to allow skolems in to be instantiated, as we've already rewritten-with respect to any Givens. (We're solving a Wanted here, and so-all Givens have already been processed.)--This is best understood by example.--1. C alpha ~? C Int-- That given certainly might match later.--2. C a ~? C Int-- No. No new givens are going to arise that will get the `a` to rewrite- to Int.--3. C alpha[tv] ~? C Int-- That alpha[tv] is a TyVarTv, unifiable only with other type variables.- It cannot equal later.--4. C (F alpha) ~? C Int-- Sure -- that can equal later, if we learn something useful about alpha.--5. C (F alpha[tv]) ~? C Int-- This, too, might equal later. Perhaps we have [G] F b ~ Int elsewhere.- Or maybe we have C (F alpha[tv] beta[tv]), these unify with each other,- and F x x = Int. Remember: returning True doesn't commit ourselves to- anything.--6. C (F a) ~? C a-- No, this won't match later. If we could rewrite (F a) or a, we would- have by now.--7. C (Maybe alpha) ~? C alpha-- We say this cannot equal later, because it would require- alpha := Maybe (Maybe (Maybe ...)). While such a type can be contrived,- we choose not to worry about it. See Note [Infinitary substitution in lookup]- in GHC.Core.InstEnv. Getting this wrong let to #19107, tested in- typecheck/should_compile/T19107.--8. C cbv ~? C Int- where cbv = F a-- The cbv is a cycle-breaker var which stands for F a. See- Note [Type variable cycles] in GHC.Tc.Solver.Canonical.- This is just like case 6, and we say "no". Saying "no" here is- essential in getting the parser to type-check, with its use of DisambECP.--9. C cbv ~? C Int- where cbv = F alpha-- Here, we might indeed equal later. Distinguishing between- this case and Example 8 is why we need the InertSet in mightEqualLater.--10. C (F alpha, Int) ~? C (Bool, F alpha)-- This cannot equal later, because F a would have to equal both Bool and- Int.--To deal with type family applications, we use the Core flattener. See-Note [Flattening type-family applications when matching instances] in GHC.Core.Unify.-The Core flattener replaces all type family applications with-fresh variables. The next question: should we allow these fresh-variables in the domain of a unifying substitution?--A type family application that mentions only skolems (example 6) is settled:-any skolems would have been rewritten w.r.t. Givens by now. These type family-applications match only themselves. A type family application that mentions-metavariables, on the other hand, can match anything. So, if the original type-family application contains a metavariable, we use BindMe to tell the unifier-to allow it in the substitution. On the other hand, a type family application-with only skolems is considered rigid.--This treatment fixes #18910 and is tested in-typecheck/should_compile/InstanceGivenOverlap{,2}--}- removeInertCts :: [Ct] -> InertCans -> InertCans -- ^ Remove inert constraints from the 'InertCans', for use when a -- typechecker plugin wishes to discard a given.@@ -735,7 +648,7 @@ CQuantCan {} -> panic "removeInertCt: CQuantCan" CIrredCan {} -> panic "removeInertCt: CIrredEvCan" CNonCanonical {} -> panic "removeInertCt: CNonCanonical"- CSpecialCan _ special_pred _ ->+ CSpecialCan { cc_special_pred = special_pred } -> pprPanic "removeInertCt" (ppr "CSpecialCan" <+> parens (ppr special_pred)) -- | Looks up a family application in the inerts.@@ -1099,7 +1012,8 @@ , tcs_abort_on_insoluble = abort_on_insoluble } -> do { inerts <- TcM.readTcRef old_inert_var- ; let nest_inert = inerts { inert_cycle_breakers = []+ ; let nest_inert = inerts { inert_cycle_breakers = pushCycleBreakerVarStack+ (inert_cycle_breakers inerts) , inert_cans = (inert_cans inerts) { inert_given_eqs = False } } -- All other InertSet fields are inherited@@ -1690,7 +1604,8 @@ setWantedEq (HoleDest hole) co = do { useVars (coVarsOfCo co) ; fillCoercionHole hole co }-setWantedEq (EvVarDest ev) _ = pprPanic "setWantedEq" (ppr ev)+setWantedEq (EvVarDest ev) _ = pprPanic "setWantedEq: EvVarDest" (ppr ev)+setWantedEq NoDest _ = panic "setWantedEq: NoDest" -- | Good for both equalities and non-equalities setWantedEvTerm :: TcEvDest -> EvTerm -> TcS ()@@ -1706,6 +1621,8 @@ setWantedEvTerm (EvVarDest ev_id) tm = setEvBind (mkWantedEvBind ev_id tm)+setWantedEvTerm NoDest tm+ = pprPanic "setWantedEvTerm: NoDest" (ppr tm) {- Note [Yukky eq_sel for a HoleDest] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -1773,7 +1690,8 @@ ; updWorkListTcS (extendWorkListEq (mkNonCanonical ev)) ; return co } --- | Make a new equality CtEvidence+-- | Create a new Wanted constraint holding a coercion hole+-- for an equality between the two types at the given 'Role'. newWantedEq :: CtLoc -> RewriterSet -> Role -> TcType -> TcType -> TcS (CtEvidence, Coercion) newWantedEq loc rewriters role ty1 ty2@@ -1787,7 +1705,9 @@ where pty = mkPrimEqPredRole role ty1 ty2 --- no equalities here. Use newWantedEq instead+-- | Create a new Wanted constraint holding an evidence variable.+--+-- Don't use this for equality constraints: use 'newWantedEq' instead. newWantedEvVarNC :: CtLoc -> RewriterSet -> TcPredType -> TcS CtEvidence -- Don't look up in the solved/inerts; we know it's not there@@ -1800,11 +1720,19 @@ , ctev_loc = loc , ctev_rewriters = rewriters })} +-- | Like 'newWantedEvVarNC', except it might look up in the inert set+-- to see if an inert already exists, and uses that instead of creating+-- a new Wanted constraint.+--+-- Don't use this for equality constraints: this function is only for+-- constraints with 'EvVarDest'. newWantedEvVar :: CtLoc -> RewriterSet -> TcPredType -> TcS MaybeNew -- For anything except ClassPred, this is the same as newWantedEvVarNC newWantedEvVar loc rewriters pty- = assert (not (isHoleDestPred pty)) $+ = assertPpr (not (isEqPrimPred pty))+ (vcat [ text "newWantedEvVar: HoleDestPred"+ , text "pty:" <+> ppr pty ]) $ do { mb_ct <- lookupInInerts loc pty ; case mb_ct of Just ctev@@ -1813,16 +1741,24 @@ _ -> do { ctev <- newWantedEvVarNC loc rewriters pty ; return (Fresh ctev) } } +-- | Create a new Wanted constraint, potentially looking up+-- non-equality constraints in the cache instead of creating+-- a new one from scratch.+--+-- Deals with both equality and non-equality constraints. newWanted :: CtLoc -> RewriterSet -> PredType -> TcS MaybeNew--- Deals with both equalities and non equalities. Tries to look--- up non-equalities in the cache newWanted loc rewriters pty | Just (role, ty1, ty2) <- getEqPredTys_maybe pty = Fresh . fst <$> newWantedEq loc rewriters role ty1 ty2 | otherwise = newWantedEvVar loc rewriters pty --- deals with both equalities and non equalities. Doesn't do any cache lookups.+-- | Create a new Wanted constraint.+--+-- Deals with both equality and non-equality constraints.+--+-- Does not attempt to re-use non-equality constraints that already+-- exist in the inert set. newWantedNC :: CtLoc -> RewriterSet -> PredType -> TcS CtEvidence newWantedNC loc rewriters pty | Just (role, ty1, ty2) <- getEqPredTys_maybe pty@@ -1974,8 +1910,8 @@ ; traceTcS "breakTyVarCycle replacing type family in Given" (ppr new_given) ; emitWorkNC [new_given] ; updInertTcS $ \is ->- is { inert_cycle_breakers = (new_tv, fun_app) :- inert_cycle_breakers is }+ is { inert_cycle_breakers = insertCycleBreakerBinding new_tv fun_app+ (inert_cycle_breakers is) } ; return $ mkReflRedn Nominal new_ty } -- Why reflexive? See Detail (4) of the Note @@ -1995,8 +1931,9 @@ -- See Note [Type variable cycles] in GHC.Tc.Solver.Canonical. restoreTyVarCycles :: InertSet -> TcM () restoreTyVarCycles is- = forM_ (inert_cycle_breakers is) $ \ (cycle_breaker_tv, orig_ty) ->- TcM.writeMetaTyVar cycle_breaker_tv orig_ty+ = forAllCycleBreakerBindings_ (inert_cycle_breakers is) TcM.writeMetaTyVar+{-# SPECIALISE forAllCycleBreakerBindings_ ::+ CycleBreakerVarStack -> (TcTyVar -> TcType -> TcM ()) -> TcM () #-} -- Unwrap a type synonym only when either: -- The type synonym is forgetful, or
compiler/GHC/Tc/TyCl.hs view
@@ -4515,7 +4515,7 @@ ; unlifted_newtypes <- xoptM LangExt.UnliftedNewtypes ; let allowedArgType =- unlifted_newtypes || isLiftedType_maybe (scaledThing arg_ty1) == Just True+ unlifted_newtypes || typeLevity_maybe (scaledThing arg_ty1) == Just Lifted ; checkTc allowedArgType $ TcRnUnknownMessage $ mkPlainError noHints $ vcat [ text "A newtype cannot have an unlifted argument type" , text "Perhaps you intended to use UnliftedNewtypes"
compiler/GHC/Tc/TyCl/Build.hs view
@@ -211,6 +211,8 @@ -> ([InvisTVBinder], ThetaType) -- ^ Univ and req -> ([InvisTVBinder], ThetaType) -- ^ Ex and prov -> [Type] -- ^ Argument types+ -- These must have a fixed RuntimeRep as per+ -- Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete. -> Type -- ^ Result type -> [FieldLabel] -- ^ Field labels for -- a record pattern synonym
compiler/GHC/Tc/TyCl/Class.hs view
@@ -304,13 +304,12 @@ tcPolyCheck no_prag_fn local_dm_sig (L bind_loc lm_bind) - ; let export = ABE { abe_ext = noExtField- , abe_poly = global_dm_id+ ; let export = ABE { abe_poly = global_dm_id , abe_mono = local_dm_id , abe_wrap = idHsWrapper , abe_prags = IsDefaultMethod }- full_bind = AbsBinds { abs_ext = noExtField- , abs_tvs = tyvars+ full_bind = XHsBindsLR $+ AbsBinds { abs_tvs = tyvars , abs_ev_vars = [this_dict] , abs_exports = [export] , abs_ev_binds = [ev_binds]
compiler/GHC/Tc/TyCl/Instance.hs view
@@ -1321,14 +1321,13 @@ -- Newtype dfuns just inline unconditionally, -- so don't attempt to specialise them - export = ABE { abe_ext = noExtField- , abe_wrap = idHsWrapper+ export = ABE { abe_wrap = idHsWrapper , abe_poly = dfun_id_w_prags , abe_mono = self_dict , abe_prags = dfun_spec_prags } -- NB: see Note [SPECIALISE instance pragmas]- main_bind = AbsBinds { abs_ext = noExtField- , abs_tvs = inst_tyvars+ main_bind = XHsBindsLR $+ AbsBinds { abs_tvs = inst_tyvars , abs_ev_vars = dfun_ev_vars , abs_exports = [export] , abs_ev_binds = []@@ -1475,14 +1474,13 @@ ; let sc_top_ty = mkInfForAllTys tyvars $ mkPhiTy (map idType dfun_evs) sc_pred sc_top_id = mkLocalId sc_top_name Many sc_top_ty- export = ABE { abe_ext = noExtField- , abe_wrap = idHsWrapper+ export = ABE { abe_wrap = idHsWrapper , abe_poly = sc_top_id , abe_mono = sc_ev_id , abe_prags = noSpecPrags } local_ev_binds = TcEvBinds ev_binds_var- bind = AbsBinds { abs_ext = noExtField- , abs_tvs = tyvars+ bind = XHsBindsLR $+ AbsBinds { abs_tvs = tyvars , abs_ev_vars = dfun_evs , abs_exports = [export] , abs_ev_binds = [dfun_ev_binds, local_ev_binds]@@ -1910,15 +1908,14 @@ ; spec_prags <- tcSpecPrags global_meth_id prags ; let specs = mk_meth_spec_prags global_meth_id spec_inst_prags spec_prags- export = ABE { abe_ext = noExtField- , abe_poly = global_meth_id+ export = ABE { abe_poly = global_meth_id , abe_mono = local_meth_id , abe_wrap = idHsWrapper , abe_prags = specs } local_ev_binds = TcEvBinds ev_binds_var- full_bind = AbsBinds { abs_ext = noExtField- , abs_tvs = tyvars+ full_bind = XHsBindsLR $+ AbsBinds { abs_tvs = tyvars , abs_ev_vars = dfun_ev_vars , abs_exports = [export] , abs_ev_binds = [dfun_ev_binds, local_ev_binds]@@ -1968,14 +1965,13 @@ ; (tc_bind, [inner_id]) <- tcPolyCheck no_prag_fn inner_meth_sig meth_bind - ; let export = ABE { abe_ext = noExtField- , abe_poly = local_meth_id+ ; let export = ABE { abe_poly = local_meth_id , abe_mono = inner_id , abe_wrap = hs_wrap , abe_prags = noSpecPrags } - ; return (unitBag $ L (getLoc meth_bind) $- AbsBinds { abs_ext = noExtField, abs_tvs = [], abs_ev_vars = []+ ; return (unitBag $ L (getLoc meth_bind) $ XHsBindsLR $+ AbsBinds { abs_tvs = [], abs_ev_vars = [] , abs_exports = [export] , abs_binds = tc_bind, abs_ev_binds = [] , abs_sig = True }) }
compiler/GHC/Tc/TyCl/PatSyn.hs view
@@ -669,7 +669,10 @@ -> TcPragEnv -> ([TcInvisTVBinder], [PredType], TcEvBinds, [EvVar]) -> ([TcInvisTVBinder], [TcType], [PredType], [EvTerm])- -> ([LHsExpr GhcTc], [TcType]) -- ^ Pattern arguments and types+ -> ([LHsExpr GhcTc], [TcType])+ -- ^ Pattern arguments and types.+ -- These must have a fixed RuntimeRep as per+ -- Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete. -> TcType -- ^ Pattern type -> [FieldLabel] -- ^ Selector names -- ^ Whether fields, empty if not record PatSyn@@ -869,6 +872,8 @@ = do { builder_name <- newImplicitBinder name mkBuilderOcc ; let theta = req_theta ++ prov_theta need_dummy_arg = isUnliftedType pat_ty && null arg_tys && null theta+ -- NB: pattern arguments cannot be representation-polymorphic,+ -- as checked in 'tcPatSynSig'. So 'isUnliftedType' is OK here. builder_sigma = add_void need_dummy_arg $ mkInvisForAllTys univ_bndrs $ mkInvisForAllTys ex_bndrs $
compiler/GHC/Tc/TyCl/Utils.hs view
@@ -971,14 +971,14 @@ eq_subst = mkTvSubstPrs (map eqSpecPair eq_spec) -- inst_tys corresponds to one of the following: --- -- * The arguments to the user-written return type (for GADT constructors).- -- In this scenario, eq_subst provides a mapping from the universally- -- quantified type variables to the argument types. Note that eq_subst- -- does not need to be applied to any other part of the DataCon- -- (see Note [The dcEqSpec domain invariant] in GHC.Core.DataCon).- -- * The universally quantified type variables- -- (for Haskell98-style constructors and pattern synonyms). In these- -- scenarios, eq_subst is an empty substitution.+ -- * The arguments to the user-written return type (for GADT constructors).+ -- In this scenario, eq_subst provides a mapping from the universally+ -- quantified type variables to the argument types. Note that eq_subst+ -- does not need to be applied to any other part of the DataCon+ -- (see Note [The dcEqSpec domain invariant] in GHC.Core.DataCon).+ -- * The universally quantified type variables+ -- (for Haskell98-style constructors and pattern synonyms). In these+ -- scenarios, eq_subst is an empty substitution. inst_tys = substTyVars eq_subst univ_tvs unit_rhs = mkLHsTupleExpr [] noExtField
compiler/GHC/Tc/Utils/Concrete.hs view
@@ -1,38 +1,48 @@ {-# LANGUAGE MultiWayIf #-} +-- | Checking for representation-polymorphism using the Concrete mechanism.+--+-- This module contains the logic for enforcing the representation-polymorphism+-- invariants by way of emitting constraints. module GHC.Tc.Utils.Concrete- ( -- * Creating/emitting 'Concrete#' constraints+ ( -- * Ensuring that a type has a fixed runtime representation hasFixedRuntimeRep- , newConcretePrimWanted- -- * HsWrapper: checking for representation-polymorphism- , mkWpFun+ , hasFixedRuntimeRep_MustBeRefl ) where import GHC.Prelude -import GHC.Core.Coercion ( multToCo )-import GHC.Core.Type ( isConcrete, typeKind )-import GHC.Core.TyCo.Rep--import GHC.Tc.Utils.Monad-import GHC.Tc.Utils.TcType ( mkTyConApp )-import GHC.Tc.Utils.TcMType-import GHC.Tc.Types.Constraint-import GHC.Tc.Types.Evidence-import GHC.Tc.Types.Origin ( CtOrigin(..), FRROrigin(..), WpFunOrigin(..) )+import GHC.Builtin.Types ( unliftedTypeKindTyCon, liftedTypeKindTyCon ) -import GHC.Builtin.Types ( unliftedTypeKindTyCon, liftedTypeKindTyCon )-import GHC.Builtin.Types.Prim ( concretePrimTyCon )+import GHC.Core.Coercion ( Role(..) )+import GHC.Core.Predicate ( mkIsReflPrimPred )+import GHC.Core.TyCo.Rep ( Type(TyConApp), mkTyVarTy )+import GHC.Core.Type ( isConcrete, typeKind ) -import GHC.Types.Basic ( TypeOrKind(KindLevel) )+import GHC.Tc.Types ( TcM, ThStage(Brack), PendingStuff(TcPending) )+import GHC.Tc.Types.Constraint ( mkNonCanonical )+import GHC.Tc.Types.Evidence ( TcCoercion )+import GHC.Tc.Types.Origin ( CtOrigin(..), FRROrigin(..) )+import GHC.Tc.Utils.Monad ( emitSimple, getStage )+import GHC.Tc.Utils.TcType ( TcType, TcKind, TcTyVar, MetaInfo(ConcreteTv) )+import GHC.Tc.Utils.TcMType ( newAnonMetaTyVar, newWanted, emitWantedEq ) +import GHC.Types.Basic ( TypeOrKind(..) ) +import GHC.Utils.Misc ( HasDebugCallStack )+import GHC.Utils.Outputable+import GHC.Utils.Panic ( assertPpr ) {- Note [Concrete overview] ~~~~~~~~~~~~~~~~~~~~~~~~~~~-Special predicates of the form `Concrete# ty` are used-to check, in the typechecker, that certain types have a fixed runtime representation.+GHC ensures that certain types have a fixed runtime representation in the+typechecker, by emitting certain constraints.+Emitting constraints to be solved later allows us to accept more programs:+if we directly inspected the type (using e.g. `typePrimRep`), we might not+have enough information available (e.g. if the type has kind `TYPE r` for+a metavariable `r` which has not yet been filled in.)+ We give here an overview of the various moving parts, to serve as a central point of reference for this topic. @@ -50,20 +60,26 @@ So, instead of checking immediately, we emit a constraint. * What does it mean for a type to be concrete?- Note [Concrete types]+ Note [Concrete types] explains what it means for a type to be concrete.++ To compute which representation to use for a type, `typePrimRep` expects+ its kind to be concrete: something specific like `BoxedRep Lifted` or+ `IntRep`; certainly not a type involving type variables or type families.++ * What constraints do we emit? Note [The Concrete mechanism] - The predicate 'Concrete# ty' is satisfied when we can produce- a coercion+ Instead of simply checking that a type `ty` is concrete (i.e. computing+ 'isConcrete`), we emit an equality constraint: - co :: ty ~ concrete_ty+ co :: ty ~# concrete_ty - where 'concrete_ty' consists only of concrete types (no type variables,- no type families).+ where 'concrete_ty' is a concrete metavariable: a metavariable whose 'MetaInfo'+ is 'ConcreteTv', signifying that it can only be unified with a concrete type. - The first note explains more precisely what it means for a type to be concrete.- The second note explains how this relates to the `Concrete#` predicate,- and explains that the implementation is happening in two phases (PHASE 1 and PHASE 2).+ The Note explains that this allows us to accept more programs. The Note+ also explains that the implementation is happening in two phases+ (PHASE 1 and PHASE 2). In PHASE 1 (the current implementation) we only allow trivial evidence of the form `co = Refl`. @@ -72,42 +88,29 @@ We currently enforce the representation-polymorphism invariants by checking that binders and function arguments have a "fixed RuntimeRep".- That is, `ty :: ki` has a "fixed RuntimeRep" if we can solve `Concrete# ki`. This is slightly less general than we might like, as this rules out types with kind `TYPE (BoxedRep l)`: we know that this will be represented by a pointer, which should be enough to go on in many situations. - * When do we emit 'Concrete#' constraints?+ * When do we emit these constraints? Note [hasFixedRuntimeRep] - We introduce 'Concrete#' constraints to satisfy the representation-polymorphism+ We introduce constraints to satisfy the representation-polymorphism invariants outlined in Note [Representation polymorphism invariants] in GHC.Core, which mostly amounts to the following two cases: - checking that a binder has a fixed runtime representation, - checking that a function argument has a fixed runtime representation. - The note explains precisely how we emit these 'Concrete#' constraints.-- * How do we solve Concrete# constraints?- Note [Solving Concrete# constraints] in GHC.Tc.Instance.Class-- Concrete# constraints are solved through two mechanisms,- which are both explained further in the note:-- - by decomposing them, e.g. `Concrete# (TYPE r)` is turned- into `Concrete# r` (canonicalisation of `Concrete#` constraints),- - by using 'Concrete' instances (top-level interactions).- The note explains that the evidence we get from using such 'Concrete'- instances can only ever be Refl, even in PHASE 2.+ The Note explains precisely how and where these constraints are emitted. - * Reporting unsolved Concrete# constraints+ * Reporting unsolved constraints Note [Reporting representation-polymorphism errors] in GHC.Tc.Types.Origin - When we emit a 'Concrete#' constraint, we also provide a 'FRROrigin'- which gives context about the check being done. This origin gets reported- to the user if we end up with an unsolved Wanted 'Concrete#' constraint.+ When we emit a constraint to enforce a fixed representation, we also provide+ a 'FRROrigin' which gives context about the check being done. This origin gets+ reported to the user if we end up with such an an unsolved Wanted constraint. Note [Representation polymorphism checking] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -157,17 +160,12 @@ See Note [Concrete overview] in GHC.Tc.Utils.Concrete for an overview of the various moving parts. - The idea is that, to guarantee that a type (rr :: RuntimeRep) is- representation-monomorphic, we emit a 'Concrete# rr' Wanted constraint.- If GHC can solve this constraint, it means 'rr' is monomorphic, and we- are OK to proceed. Otherwise, we report this unsolved Wanted in the form- of a representation-polymorphism error. The different contexts in which- such constraints arise are enumerated in 'FRROrigin'.- Note [Concrete types] ~~~~~~~~~~~~~~~~~~~~~-Definition: a type is /concrete/- iff it consists of a tree of concrete type constructors+Definition: a type is /concrete/ iff it is:+ - a concrete type constructor (as defined below), or+ - a concrete type variable (see Note [ConcreteTv] below), or+ - an application of a concrete type to another concrete type See GHC.Core.Type.isConcrete Definition: a /concrete type constructor/ is defined by@@ -182,69 +180,57 @@ Examples of concrete types: Lifted, BoxedRep Lifted, TYPE (BoxedRep Lifted) are all concrete Examples of non-concrete types- F Int, TYPE (F Int), TYPE r, a Int+ F Int, TYPE (F Int), TYPE r, a[sk] NB: (F Int) is not concrete because F is a type function -Note [The Concrete mechanism]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-As explained in (2) in Note [Representation polymorphism checking],-to check (ty :: ki) has a fixed runtime representation,-we emit a `Concrete# ki` constraint, where-- Concrete# :: forall k. k -> TupleRep '[]--Such constraints get solved by decomposition, as per- Note [Canonical Concrete# constraints] in GHC.Tc.Solver.Canonical.-When unsolved Wanted `Concrete#` constraints remain after typechecking,-we report them as representation-polymorphism errors, using `GHC.Tc.Types.Origin.FRROrigin`-to inform the user of the context in which a fixed-runtime-rep check arose.------------------- EVIDENCE -------------------The evidence for a 'Concrete# ty' constraint is a nominal coercion-- co :: ty ~# concrete_ty+The recursive definition of concreteness entails the following property: -where 'concrete_ty' consists only of (non-synonym) type constructors and applications-(after expanding any vanilla type synonyms).+Concrete Congruence Property (CCP)+ All sub-trees of a concrete type tree are concrete. - OK:+The following property also holds due to the invariant that the kind of a+concrete metavariable is itself concrete (see Note [ConcreteTv]): - TYPE FloatRep- TYPE (BoxedRep Lifted)- Type- TYPE (TupleRep '[ FloatRep, SumRep '[ IntRep, IntRep ] ])+Concrete Kinds Property (CKP)+ The kind of a concrete type is concrete. - Not OK:+The CCP and the CKP taken together mean that we never have to inspect+in kinds to check concreteness. - Type variables:+Note [ConcreteTv]+~~~~~~~~~~~~~~~~~+A concrete metavariable is a metavariable whose 'MetaInfo' is 'ConcreteTv'.+Similar to 'TyVarTv's which are type variables which can only be unified with+other type variables, a 'ConcreteTv' type variable is a type variable which can+only be unified with a concrete type (in the sense of Note [Concrete types]). - ty- TYPE r- TYPE (BoxedRep l)+INVARIANT: the kind of a concrete metavariable is concrete. - Type family applications:+This invariant is upheld at the time of creation of a new concrete metavariable. - TYPE (Id FloatRep)+Concrete metavariables are useful for representation-polymorphism checks:+they allow us to refer to a type whose representation is not yet known but will+be figured out by the typechecker (see Note [The Concrete mechanism]). -This is so that we can compute the 'PrimRep's needed to represent the type-using 'runtimeRepPrimRep', which expects to be able to read off the 'RuntimeRep',-as per Note [Getting from RuntimeRep to PrimRep] in GHC.Types.RepType.+Note [The Concrete mechanism]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+To check (ty :: ki) has a fixed runtime representation, we proceed as follows: -Note that the evidence for a `Concrete#` constraint isn't a typeclass dictionary:-like with `(~#)`, the evidence is an (unlifted) nominal coercion, which justifies defining+ - Create a new concrete metavariable `concrete_tv`, i.e. a metavariable+ with 'ConcreteTv' 'MetaInfo' (see Note [ConcreteTv]). - Concrete# :: forall k. k -> TYPE (TupleRep '[])+ - Emit an equality constraint: -We still need a constraint that users can write in their own programs,-so much like `(~#)` and `(~)` we also define:+ ki ~# concrete_tv - Concrete :: forall k. k -> Constraint+ The origin for such an equality constraint uses+ `GHC.Tc.Types.Origin.FRROrigin`, so that we can report the appropriate+ representation-polymorphism error if any such constraint goes unsolved. -The need for user-facing 'Concrete' constraints is detailed in- Note [Concrete and Concrete#] in GHC.Builtin.Types.+To solve `ki ~# concrete_ki`, we must unify `concrete_tv := concrete_ki`,+where `concrete_ki` is some concrete type. We can then compute `kindPrimRep`+on `concrete_ki` to compute the representation: this means `ty` indeed+has a fixed runtime representation. ------------------------- -- PHASE 1 and PHASE 2 --@@ -252,15 +238,20 @@ The Concrete mechanism is being implemented in two separate phases. -In PHASE 1 (currently implemented), we never allow a 'Concrete#' constraint-to be rewritten (see e.g. GHC.Tc.Solver.Canonical.canConcretePrim).-The only allowable evidence term is Refl, which forbids any program-that requires type family evaluation in order to determine that a 'RuntimeRep' is fixed.-N.B.: we do not currently check that this invariant is upheld: as we are discarding the-evidence in PHASE 1, we no longer have access to the coercion after constraint solving-(which is the point at which we would want to check that the filled in evidence is Refl).+In PHASE 1 (currently implemented), we enforce that we only solve the emitted+constraints `co :: ki ~# concrete_tv` with `Refl`. This forbids any program+which requires type family evaluation in order to determine that a 'RuntimeRep'+is fixed. We do this using the `IsRefl#` special predicate (see Note [IsRefl#]);+we only solve `IsRefl# a b` if `a` and `b` are equal (after zonking, but not rewriting).+This means that it is safe to not use the coercion `co` anywhere in the program.+PHASE 1 corresponds to calls to `hasFixedRuntimeRep_MustBeRefl` in the code: on top+of emitting a constraint of the form `ki ~# concrete_tv`, we also emit+`IsRefl# ki concrete_tv` to ensure we only solve the equality constraint using+reflexivity. -In PHASE 2 (future work), we lift this restriction. To illustrate what this entails,+In PHASE 2, we lift this restriction. This means we replace a call to+`hasFixedRuntimeRep_MustBeRefl` with a call to `hasFixedRuntimeRep`, and insert the+obtained coercion in the typechecked result. To illustrate what this entails, recall that the code generator needs to be able to compute 'PrimRep's, so that it can put function arguments in the correct registers, etc. As a result, we must insert additional casts in Core to ensure that no type family@@ -275,7 +266,7 @@ f = /\ ( a :: F Int ). \ ( x :: ( a |> kco ) ). some_expression -where 'kco' is the evidence for `Concrete# (F Int)`, for example if `F Int = TYPE Int#`+where 'kco' is the appropriate coercion; for example if `F Int = TYPE Int#` this would be: kco :: F Int ~# TYPE Int#@@ -289,12 +280,9 @@ ~~~~~~~~~~~~~~~~~~~~~~~ Definition: a type `ty :: ki` has a /fixed RuntimeRep/- iff we can solve `Concrete# ki`--In PHASE 1 (see Note [The Concrete mechanism]), this is equivalent to:-- a type `ty :: ki` has a /fixed RuntimeRep/- iff `ki` is a concrete type (in the sense of Note [Concrete types]).+ <=>+ there exists a concrete type `concrete_ty` (in the sense of Note [Concrete types])+ such that we can solve `ki ~# concrete_ty`. This definition is crafted to be useful to satisfy the invariants of Core; see Note [Representation polymorphism invariants] in GHC.Core.@@ -312,10 +300,11 @@ Note [hasFixedRuntimeRep] ~~~~~~~~~~~~~~~~~~~~~~~~~ The 'hasFixedRuntimeRep' function is responsible for taking a type 'ty'-and emitting a 'Concrete#' constraint to ensure that 'ty' has a fixed `RuntimeRep`,+and emitting a constraint to ensure that 'ty' has a fixed `RuntimeRep`, as outlined in Note [The Concrete mechanism]. -To do so, we compute the kind 'ki' of 'ty' and emit a 'Concrete# ki' constraint,+To do so, we compute the kind 'ki' of 'ty', create a new concrete metavariable+`concrete_tv` of kind `ki`, and emit a constraint `ki ~# concrete_tv`, which will only be solved if we can prove that 'ty' indeed has a fixed RuntimeRep. [Wrinkle: Typed Template Haskell]@@ -350,158 +339,131 @@ Test case: rep-poly/T18170a. -Note [Solving Concrete# constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The representation polymorphism checks emit 'Concrete# ty' constraints,-as explained in Note [hasFixedRuntimeRep] in GHC.Tc.Utils.Concrete.--The main mechanism through which a `Concrete# ty` constraint is solved-is to directly inspect 'ty' to check that it is a concrete type-such as 'TYPE IntRep' or `TYPE (TupleRep '[ TupleRep '[], FloatRep ])`,-and not, e.g., a skolem type variable.--There are, however, some interactions to take into account:-- 1. Decomposition.-- The solving of `Concrete#` constraints works recursively.- For example, to solve a Wanted `Concrete# (TYPE r)` constraint,- we decompose it, emitting a new `Concrete# @RuntimeRep r` Wanted constraint,- and use it to solve the original `Concrete# (TYPE r)` constraint.- This happens in the canonicaliser -- see GHC.Tc.Solver.Canonical.canDecomposableConcretePrim.-- Note that Decomposition fully solves `Concrete# ty` whenever `ty` is a- concrete type. For example:-- Concrete# (TYPE (BoxedRep Lifted))- ==> (decompose)- Concrete# (BoxedRep Lifted)- ==> (decompose)- Concrete# Lifted- ==> (decompose)- <nothing, since Lifted is nullary>-- 2. Rewriting.-- In PHASE 1 (as per Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete),- we don't have to worry about a 'Concrete#' constraint being rewritten.- We only need to zonk: if e.g. a metavariable, `alpha`, gets unified with `IntRep`,- we should be able to solve `Concrete# alpha`.+Note [IsRefl#]+~~~~~~~~~~~~~~+`IsRefl# :: forall k. k -> k -> TYPE (TupleRep '[])` is a constraint with no+evidence. `IsRefl# a b' can be solved precisely when `a` and `b` are equal (up to zonking,+but __without__ any rewriting). - In PHASE 2, we will need to proceed as in GHC.Tc.Solver.Canonical.canClass:- if we have a constraint `Concrete# (F ty1)` and a coercion witnessing the reduction of- `F`, say `co :: F ty1 ~# ty2`, then we will solve `Concrete# (F ty1)` in terms of `Concrete# ty2`,- by rewriting the evidence for `Concrete# ty2` using `co` (see GHC.Tc.Solver.Canonical.rewriteEvidence).+That is, if we have a type family `F` with `F Int` reducing to `Int`, we __cannot__ solve+`IsRefl# (F Int) Int`. - 3. Backpack+What is the point of such a constraint? As outlined in Note [The Concrete mechanism],+to check `ty :: ki` has a fixed RuntimeRep we create a concrete metavariable `concrete_tv`+and emit a Wanted equality constraint - Abstract 'TyCon's in Backpack signature files are always considered to be concrete.- This is because of the strong restrictions around how abstract types are allowed- to be implemented, as laid out in Note [Synonyms implement abstract data] in GHC.Tc.Module.- In particular, no variables or type family applications are allowed.+ {co_hole} :: ki ~# concrete_tv - Examples: backpack/should_run/T13955.bkp, rep-poly/RepPolyBackpack2.+Then, when we fill in the coercion hole with a coercion `co`, we must make use of it+(as that Note explains). If we don't, then we can only safely discard it if it is+reflexive. Therefore, whenever we perform a representation polymorphism check but also+discard the resulting coercion, we also emit a special constraint `IsRefl# ki concrete_tv`.+See 'hasFixedRuntimeRep_MustBeRefl', which calls 'hasFixedRuntimeRep', and thenemits+an 'IsRefl#' constraint to ensure that discarding the coercion is safe. -} --- | Evidence for a `Concrete#` constraint:--- essentially a 'ConcreteHole' (a coercion hole) that will be filled later,--- except:------ - we might already have the evidence now; no point in creating a coercion hole--- in that case;--- - we sometimes skip the check entirely, e.g. in Typed Template Haskell--- (see [Wrinkle: Typed Template Haskell] in Note [hasFixedRuntimeRep]).-data ConcreteEvidence- = ConcreteReflEvidence- -- ^ We have evidence right now: don't bother creating a 'ConcreteHole'.- | ConcreteTypedTHNoEvidence- -- ^ We don't emit 'Concrete#' constraints in Typed Template Haskell.- -- See [Wrinkle: Typed Template Haskell] in Note [hasFixedRuntimeRep].- | ConcreteHoleEvidence ConcreteHole- -- ^ The general form of evidence: a 'ConcreteHole' that should be- -- filled in later by the constraint solver, as per- -- Note [Solving Concrete# constraints].---- | Check that the kind of the provided type is of the form--- @TYPE rep@ for a __fixed__ 'RuntimeRep' @rep@.------ If this isn't immediately obvious, for instance if the 'RuntimeRep'--- is hidden under a type-family application such as+-- | Like 'hasFixedRuntimeRep', but we insist that the obtained coercion must be 'Refl'. ----- > ty :: TYPE (F x)+-- This is useful if we are not actually going to use the coercion returned+-- from 'hasFixedRuntimeRep'; it would generally be unsound to allow a non-reflexive+-- coercion but not actually make use of it in a cast. See Note [IsRefl#]. ----- this function will emit a new Wanted 'Concrete#' constraint.-hasFixedRuntimeRep :: FRROrigin -> Type -> TcM ConcreteEvidence-hasFixedRuntimeRep frrOrig ty-- -- Shortcut: check for 'Type' and 'UnliftedType' type synonyms.- | TyConApp tc [] <- ki- , tc == liftedTypeKindTyCon || tc == unliftedTypeKindTyCon- = return ConcreteReflEvidence+-- The goal is to eliminate all uses of this function and replace them with+-- 'hasFixedRuntimeRep', making use of the returned coercion.+hasFixedRuntimeRep_MustBeRefl :: FRROrigin -> TcType -> TcM ()+hasFixedRuntimeRep_MustBeRefl frr_orig ty+ = do { -- STEP 1: check that the type has a fixed 'RuntimeRep'.+ mb_co <- hasFixedRuntimeRep frr_orig ty+ -- STEP 2: ensure that we only solve using a reflexive coercion.+ ; case mb_co of+ -- If the coercion is immediately reflexive: we're OK.+ { Nothing -> return ()+ -- Otherwise: emit an @IsRefl#@ constraint.+ -- This means we are free to discard the coercion.+ ; Just (ki, _co, concrete_kv) ->+ do { isRefl_ctev <- newWanted (FixedRuntimeRepOrigin ty frr_orig)+ (Just KindLevel) $+ mkIsReflPrimPred ki (mkTyVarTy concrete_kv)+ ; emitSimple $ mkNonCanonical isRefl_ctev } } } - | otherwise+-- | Given a type @ty :: ki@, this function ensures that @ty@+-- has a __fixed__ 'RuntimeRep', by emitting a new equality constraint+-- @ki ~ concrete_tv@ for a concrete metavariable @concrete_tv@.+--+-- Returns a coercion @co :: ki ~# concrete_tv@ as evidence.+-- If @ty@ obviously has a fixed 'RuntimeRep', e.g @ki = IntRep@,+-- then this function immediately returns 'Nothing'+-- instead of emitting a new constraint.+hasFixedRuntimeRep :: FRROrigin -- ^ Context to be reported to the user+ -- if the type ends up not having a fixed+ -- 'RuntimeRep' (unsolved Wanted constraint).+ -> TcType -- ^ The type to check (we only look at its kind).+ -> TcM (Maybe (TcType, TcCoercion, TcTyVar) )+ -- ^ @Just ( ki, co, concrete_tv )@+ -- where @co :: ki ~# concrete_ty@ is evidence that+ -- the type @ty :: ki@ has a fixed 'RuntimeRep',+ -- or 'Nothing' if 'ki' responds 'True' to 'isConcrete',+ -- (i.e. we can take @co = Refl@).+hasFixedRuntimeRep frr_orig ty = do { th_stage <- getStage ; if- -- We have evidence for 'Concrete# ty' right now:- -- no need to emit a constraint/create an evidence hole.- | isConcrete ki- -> return ConcreteReflEvidence+ -- Shortcut: check for 'Type' and 'UnliftedType' type synonyms.+ | TyConApp tc [] <- ki+ , tc == liftedTypeKindTyCon || tc == unliftedTypeKindTyCon+ -> return Nothing -- See [Wrinkle: Typed Template Haskell] in Note [hasFixedRuntimeRep]. | Brack _ (TcPending {}) <- th_stage- -> return ConcreteTypedTHNoEvidence+ -> return Nothing - -- Create a new Wanted 'Concrete#' constraint and emit it. | otherwise- -> do { loc <- getCtLocM (FixedRuntimeRepOrigin ty frrOrig) (Just KindLevel)- ; (hole, _, ct_ev) <- newConcretePrimWanted loc ki- ; emitSimple $ mkNonCanonical ct_ev- ; return $ ConcreteHoleEvidence hole } }+ -- Ensure that the kind 'ki' of 'ty' is concrete.+ -> emitNewConcreteWantedEq_maybe orig ki+ -- NB: the kind of 'ki' is 'Data.Kind.Type', which is concrete.+ -- This means that the invariant required to call+ -- 'newConcreteTyVar' is satisfied.+ } where- ki :: Kind+ ki :: TcKind ki = typeKind ty---- | Create a new 'Concrete#' constraint.--- Returns the evidence, a metavariable which will be filled in with a--- guaranteed-concrete type, and a Wanted CtEvidence-newConcretePrimWanted :: CtLoc -> Type -> TcM (ConcreteHole, TcType, CtEvidence)-newConcretePrimWanted loc ty- = do { let- ki :: Kind- ki = typeKind ty- ; (hole, concrete_ty) <- newConcreteHole ki ty- ; let- wantedCtEv :: CtEvidence- wantedCtEv =- CtWanted- { ctev_dest = HoleDest hole- , ctev_pred = mkTyConApp concretePrimTyCon [ki, ty]- , ctev_rewriters = emptyRewriterSet- , ctev_loc = loc- }- ; return (hole, concrete_ty, wantedCtEv) }+ orig :: CtOrigin+ orig = FixedRuntimeRepOrigin ty frr_orig -{-***********************************************************************-* *- HsWrapper-* *-***********************************************************************-}+-- | Create a new metavariable, of the given kind, which can only be unified+-- with a concrete type.+--+-- Invariant: the kind must be concrete, as per Note [ConcreteTv].+-- This is checked with an assertion.+newConcreteTyVar :: HasDebugCallStack => TcKind -> TcM TcTyVar+newConcreteTyVar kind =+ assertPpr (isConcrete kind)+ (text "newConcreteTyVar: non-concrete kind" <+> ppr kind)+ $ newAnonMetaTyVar ConcreteTv kind --- | Smart constructor to create a 'WpFun' 'HsWrapper'.+-- | Create a new concrete metavariable @concrete_tv@ and emit a new non-canonical Wanted+-- equality constraint @ty ~# concrete_tv@ with the given 'CtOrigin'. ----- Might emit a 'Concrete#' constraint, to check for--- representation polymorphism. This is necessary, as 'WpFun' will desugar to--- a lambda abstraction, whose binder must have a fixed runtime representation.-mkWpFun :: HsWrapper -> HsWrapper- -> Scaled TcType -- ^ the "from" type of the first wrapper- -> TcType -- ^ either type of the second wrapper (used only when the- -- second wrapper is the identity)- -> WpFunOrigin -- ^ what caused you to want a WpFun?- -> TcM HsWrapper-mkWpFun WpHole WpHole _ _ _ = return $ WpHole-mkWpFun WpHole (WpCast co2) (Scaled w t1) _ _ = return $ WpCast (mkTcFunCo Representational (multToCo w) (mkTcRepReflCo t1) co2)-mkWpFun (WpCast co1) WpHole (Scaled w _) t2 _ = return $ WpCast (mkTcFunCo Representational (multToCo w) (mkTcSymCo co1) (mkTcRepReflCo t2))-mkWpFun (WpCast co1) (WpCast co2) (Scaled w _) _ _ = return $ WpCast (mkTcFunCo Representational (multToCo w) (mkTcSymCo co1) co2)-mkWpFun co1 co2 t1 _ wpFunOrig- = do { _concrete_ev <- hasFixedRuntimeRep (FRRWpFun wpFunOrig) (scaledThing t1)- ; return $ WpFun co1 co2 t1 }+-- Short-cut: if the type responds 'True' to 'isConcrete', then+-- we already know it is concrete, so don't emit any new constraints,+-- and return 'Nothing'.+--+-- Invariant: the kind of the supplied type must be concrete.+--+-- We also assume the provided type is already at the kind-level.+--(This only matters for error messages.)+emitNewConcreteWantedEq_maybe :: CtOrigin -> TcType -> TcM (Maybe (TcType, TcCoercion, TcTyVar))+emitNewConcreteWantedEq_maybe orig ty+ -- The input type is already concrete: no need to do anything.+ -- Return 'Nothing', indicating that reflexivity is valid evidence.+ | isConcrete ty+ = return Nothing+ -- Otherwise: create a new concrete metavariable and emit a new Wanted equality constraint.+ | otherwise+ = do { concrete_tv <- newConcreteTyVar ki+ ; co <- emitWantedEq orig KindLevel Nominal ty (mkTyVarTy concrete_tv)+ -- ^^^^^^^^^ we assume 'ty' is at the kind level.+ -- (For representation polymorphism checks, we are always checking a kind.)+ ; return $ Just (ty, co, concrete_tv) }+ where+ ki :: TcKind+ ki = typeKind ty
compiler/GHC/Tc/Utils/Env.hs view
@@ -24,7 +24,7 @@ tcLookupDataCon, tcLookupPatSyn, tcLookupConLike, tcLookupLocatedGlobalId, tcLookupLocatedTyCon, tcLookupLocatedClass, tcLookupAxiom,- lookupGlobal, ioLookupDataCon,+ lookupGlobal, lookupGlobal_maybe, ioLookupDataCon, addTypecheckedBinds, -- Local environment
compiler/GHC/Tc/Utils/Instantiate.hs view
@@ -97,7 +97,7 @@ import Data.List ( mapAccumL ) import qualified Data.List.NonEmpty as NE-import Control.Monad( when, unless, void )+import Control.Monad( when, unless ) import Data.Function ( on ) {-@@ -825,7 +825,7 @@ do_check :: Arity -> TcM () do_check arity = let res_ty = nTimes arity (snd . splitPiTy) ty- in void $ hasFixedRuntimeRep (FRRArrow $ ArrowFun user_expr) res_ty+ in hasFixedRuntimeRep_MustBeRefl (FRRArrow $ ArrowFun user_expr) res_ty mb_arity :: Maybe Arity mb_arity -- arity of the arrow operation, counting type-level arguments | std_nm == arrAName -- result used as an argument in, e.g., do_premap
compiler/GHC/Tc/Utils/TcMType.hs view
@@ -197,12 +197,14 @@ -- | Create a new Wanted constraint with the given 'CtLoc'. newWantedWithLoc :: CtLoc -> PredType -> TcM CtEvidence newWantedWithLoc loc pty- = do d <- case classifyPredType pty of- EqPred {} -> HoleDest <$> newCoercionHole pty- SpecialPred ConcretePrimPred ty ->- HoleDest <$> (fst <$> newConcreteHole (typeKind ty) ty)- _ -> EvVarDest <$> newEvVar pty- return $ CtWanted { ctev_dest = d+ = do dst <- case classifyPredType pty of+ EqPred {}+ -> HoleDest <$> newCoercionHole pty+ SpecialPred s+ -> case s of+ IsReflPrimPred {} -> return NoDest+ _ -> EvVarDest <$> newEvVar pty+ return $ CtWanted { ctev_dest = dst , ctev_pred = pty , ctev_loc = loc , ctev_rewriters = emptyRewriterSet }@@ -229,9 +231,6 @@ | isEqPrimPred pty = do { co_hole <- newCoercionHole pty ; return (ctev { ctev_dest = HoleDest co_hole }) }- | SpecialPred ConcretePrimPred ty <- classifyPredType pty- = do { (co_hole, _) <- newConcreteHole (typeKind ty) ty- ; return (ctev { ctev_dest = HoleDest co_hole }) } | otherwise = pprPanic "cloneWantedCtEv" (ppr pty) cloneWantedCtEv ctev = return ctev@@ -333,9 +332,9 @@ EqPred {} -> mkVarOccFS (fsLit "co") IrredPred {} -> mkVarOccFS (fsLit "irred") ForAllPred {} -> mkVarOccFS (fsLit "df")- SpecialPred special_pred _ ->- case special_pred of- ConcretePrimPred -> mkVarOccFS (fsLit "concr")+ SpecialPred s ->+ case s of+ IsReflPrimPred {} -> mkVarOccFS (fsLit "rfl") -- | Create a new 'Implication' with as many sensible defaults for its fields -- as possible. Note that the 'ic_tclvl', 'ic_binds', and 'ic_info' fields do@@ -865,6 +864,7 @@ TyVarTv -> fsLit "a" RuntimeUnkTv -> fsLit "r" CycleBreakerTv -> fsLit "b"+ ConcreteTv -> fsLit "c" newAnonMetaTyVar :: MetaInfo -> Kind -> TcM TcTyVar newAnonMetaTyVar mi = newNamedAnonMetaTyVar (metaInfoToTyVarName mi) mi@@ -2712,9 +2712,10 @@ -- If it isn't, throw a representation-polymorphism error appropriate -- for the context (as specified by the 'FixedRuntimeRepProvenance'). ----- Unlike the other representation polymorphism checks, which emit--- 'Concrete#' constraints, this function does not emit any constraints,--- as it has enough information to immediately make a decision.+-- Unlike the other representation polymorphism checks, which can emit+-- new Wanted constraints to be solved by the constraint solver, this function+-- does not emit any constraints: it has enough information to immediately+-- make a decision. -- -- See (1) in Note [Representation polymorphism checking] in GHC.Tc.Utils.Concrete checkTypeHasFixedRuntimeRep :: FixedRuntimeRepProvenance -> Type -> TcM ()
compiler/GHC/Tc/Utils/Unify.hs view
@@ -44,14 +44,13 @@ import GHC.Hs import GHC.Core.TyCo.Rep import GHC.Core.TyCo.Ppr( debugPprType )-import GHC.Tc.Utils.Concrete ( mkWpFun )+import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep_MustBeRefl ) import GHC.Tc.Utils.Env import GHC.Tc.Utils.Instantiate import GHC.Tc.Utils.Monad import GHC.Tc.Utils.TcMType import GHC.Tc.Utils.TcType - import GHC.Core.Type import GHC.Core.Coercion import GHC.Core.Multiplicity@@ -86,19 +85,29 @@ * * ********************************************************************* -} --- | matchActualFunTySigma does looks for just one function arrow--- returning an uninstantiated sigma-type+-- | 'matchActualFunTySigma' looks for just one function arrow,+-- returning an uninstantiated sigma-type.+--+-- Invariant: the returned argument type has a fixed RuntimeRep+-- as per Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.+-- See Note [Return arguments with a fixed RuntimeRep]. matchActualFunTySigma- :: SDoc -- See Note [Herald for matchExpectedFunTys]- -> Maybe TypedThing -- The thing with type TcSigmaType- -> (Arity, [Scaled TcSigmaType]) -- Total number of value args in the call, and- -- types of values args to which function has- -- been applied already (reversed)- -- Both are used only for error messages)- -> TcRhoType -- Type to analyse: a TcRhoType- -> TcM (HsWrapper, Scaled TcSigmaType, TcSigmaType)--- The /argument/ is a RhoType--- The /result/ is an (uninstantiated) SigmaType+ :: ExpectedFunTyOrigin+ -- ^ See Note [Herald for matchExpectedFunTys]+ -> Maybe TypedThing+ -- ^ The thing with type TcSigmaType+ -> (Arity, [Scaled TcSigmaType])+ -- ^ Total number of value args in the call, and+ -- types of values args to which function has+ -- been applied already (reversed)+ -- Both are used only for error messages)+ -> TcRhoType+ -- ^ Type to analyse: a TcRhoType+ -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)+-- This function takes in a type to analyse (a RhoType) and returns+-- an argument type and a result type (splitting apart a function arrow).+-- The returned argument type is a SigmaType with a fixed RuntimeRep;+-- as explained in Note [Return arguments with a fixed RuntimeRep]. -- -- See Note [matchActualFunTy error handling] for the first three arguments @@ -118,12 +127,13 @@ -- hide the forall inside a meta-variable go :: TcRhoType -- The type we're processing, perhaps after -- expanding any type synonym- -> TcM (HsWrapper, Scaled TcSigmaType, TcSigmaType)+ -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType) go ty | Just ty' <- tcView ty = go ty' go (FunTy { ft_af = af, ft_mult = w, ft_arg = arg_ty, ft_res = res_ty }) = assert (af == VisArg) $- return (idHsWrapper, Scaled w arg_ty, res_ty)+ do { hasFixedRuntimeRep_MustBeRefl (FRRExpectedFunTy herald 0) arg_ty+ ; return (idHsWrapper, Scaled w arg_ty, res_ty) } go ty@(TyVarTy tv) | isMetaTyVar tv@@ -156,6 +166,7 @@ ; mult <- newFlexiTyVarTy multiplicityTy ; let unif_fun_ty = mkVisFunTy mult arg_ty res_ty ; co <- unifyType mb_thing fun_ty unif_fun_ty+ ; hasFixedRuntimeRep_MustBeRefl (FRRExpectedFunTy herald 0) arg_ty ; return (mkWpCastN co, Scaled mult arg_ty, res_ty) } ------------@@ -187,14 +198,18 @@ Ugh! -} --- Like 'matchExpectedFunTys', but used when you have an "actual" type,--- for example in function application-matchActualFunTysRho :: SDoc -- See Note [Herald for matchExpectedFunTys]+-- | Like 'matchExpectedFunTys', but used when you have an "actual" type,+-- for example in function application.+--+-- INVARIANT: the returned arguemnt types all have a fixed RuntimeRep+-- in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.+-- See Note [Return arguments with a fixed RuntimeRep].+matchActualFunTysRho :: ExpectedFunTyOrigin -- ^ See Note [Herald for matchExpectedFunTys] -> CtOrigin- -> Maybe TypedThing -- the thing with type TcSigmaType+ -> Maybe TypedThing -- ^ the thing with type TcSigmaType -> Arity -> TcSigmaType- -> TcM (HsWrapper, [Scaled TcSigmaType], TcRhoType)+ -> TcM (HsWrapper, [Scaled TcSigmaTypeFRR], TcRhoType) -- If matchActualFunTysRho n ty = (wrap, [t1,..,tn], res_ty) -- then wrap : ty ~> (t1 -> ... -> tn -> res_ty) -- and res_ty is a RhoType@@ -216,7 +231,9 @@ (n_val_args_wanted, so_far) fun_ty ; (wrap_res, arg_tys, res_ty) <- go (n-1) (arg_ty1:so_far) res_ty1- ; wrap_fun2 <- mkWpFun idHsWrapper wrap_res arg_ty1 res_ty (WpFunFunTy fun_ty)+ ; let wrap_fun2 = mkWpFun idHsWrapper wrap_res arg_ty1 res_ty+ -- NB: arg_ty1 comes from matchActualFunTySigma, so it has+ -- a fixed RuntimeRep as neede to call mkWpFun. ; return (wrap_fun2 <.> wrap_fun1, arg_ty1:arg_tys, res_ty) } {-@@ -281,16 +298,73 @@ ExpTypes produced for arguments before it can fill in the ExpType passed in. +Note [Return arguments with a fixed RuntimeRep]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The functions++ - matchExpectedFunTys,+ - matchActualFunTySigma,+ - matchActualFunTysRho,++peel off argument types, as explained in Note [matchExpectedFunTys].+It's important that these functions return argument types that have+a fixed runtime representation, otherwise we would be in violation+of the representation-polymorphism invariants of+Note [Representation polymorphism invariants] in GHC.Core.++This is why all these functions have an additional invariant,+that the argument types they return all have a fixed RuntimeRep,+in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.++Example:++ Suppose we have++ type F :: Type -> RuntimeRep+ type family F a where { F Int = LiftedRep }++ type Dual :: Type -> Type+ type family Dual a where+ Dual a = a -> ()++ f :: forall (a :: TYPE (F Int)). Dual a+ f = \ x -> ()++ The body of `f` is a lambda abstraction, so we must be able to split off+ one argument type from its type. This is handled by `matchExpectedFunTys`+ (see 'GHC.Tc.Gen.Match.tcMatchLambda'). We end up with desugared Core that+ looks like this:++ f :: forall (a :: TYPE (F Int)). Dual (a |> (TYPE F[0]))+ f = \ @(a :: TYPE (F Int)) ->+ (\ (x :: (a |> (TYPE F[0]))) -> ())+ `cast`+ (Sub (Sym (Dual[0] <(a |> (TYPE F[0]))>)))++ Two important transformations took place:++ 1. We inserted casts around the argument type to ensure that it has+ a fixed runtime representation, as required by invariant (I1) from+ Note [Representation polymorphism invariants] in GHC.Core.+ 2. We inserted a cast around the whole lambda to make everything line up+ with the type signature. -} --- Use this one when you have an "expected" type.+-- | Use this function to split off arguments types when you have an+-- \"expected\" type.+-- -- This function skolemises at each polytype.+--+-- Invariant: this function only applies the provided function+-- to a list of argument types which all have a fixed RuntimeRep+-- in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.+-- See Note [Return arguments with a fixed RuntimeRep]. matchExpectedFunTys :: forall a.- SDoc -- See Note [Herald for matchExpectedFunTys]+ ExpectedFunTyOrigin -- See Note [Herald for matchExpectedFunTys] -> UserTypeCtxt -> Arity -> ExpRhoType -- Skolemised- -> ([Scaled ExpSigmaType] -> ExpRhoType -> TcM a)+ -> ([Scaled ExpSigmaTypeFRR] -> ExpRhoType -> TcM a) -> TcM (HsWrapper, a) -- If matchExpectedFunTys n ty = (_, wrap) -- then wrap : (t1 -> ... -> tn -> ty_r) ~> ty,@@ -320,9 +394,13 @@ go acc_arg_tys n (FunTy { ft_mult = mult, ft_af = af, ft_arg = arg_ty, ft_res = res_ty }) = assert (af == VisArg) $- do { (wrap_res, result) <- go ((Scaled mult $ mkCheckExpType arg_ty) : acc_arg_tys)+ do { let arg_pos = length acc_arg_tys -- for error messages only+ ; hasFixedRuntimeRep_MustBeRefl (FRRExpectedFunTy herald arg_pos) arg_ty+ ; (wrap_res, result) <- go ((Scaled mult $ mkCheckExpType arg_ty) : acc_arg_tys) (n-1) res_ty- ; fun_wrap <- mkWpFun idHsWrapper wrap_res (Scaled mult arg_ty) res_ty (WpFunFunExpTy orig_ty)+ ; let fun_wrap = mkWpFun idHsWrapper wrap_res (Scaled mult arg_ty) res_ty+ -- NB: we are ensuring that arg_ty has a fixed RuntimeRep,+ -- so we satisfy the precondition that mkWpFun requires. ; return ( fun_wrap, result ) } go acc_arg_tys n ty@(TyVarTy tv)@@ -351,12 +429,17 @@ defer acc_arg_tys n (mkCheckExpType ty) ------------- defer :: [Scaled ExpSigmaType] -> Arity -> ExpRhoType -> TcM (HsWrapper, a)+ defer :: [Scaled ExpSigmaTypeFRR] -> Arity -> ExpRhoType -> TcM (HsWrapper, a) defer acc_arg_tys n fun_ty = do { more_arg_tys <- replicateM n (mkScaled <$> newFlexiTyVarTy multiplicityTy <*> newInferExpType) ; res_ty <- newInferExpType ; result <- thing_inside (reverse acc_arg_tys ++ more_arg_tys) res_ty ; more_arg_tys <- mapM (\(Scaled m t) -> Scaled m <$> readExpType t) more_arg_tys+ ; zipWithM_+ ( \ i (Scaled _ arg_ty) ->+ hasFixedRuntimeRep_MustBeRefl (FRRExpectedFunTy herald i) arg_ty )+ [0..]+ more_arg_tys ; res_ty <- readExpType res_ty ; let unif_fun_ty = mkVisFunTys more_arg_tys res_ty ; wrap <- tcSubType AppOrigin ctx unif_fun_ty fun_ty@@ -364,7 +447,7 @@ ; return (wrap, result) } ------------- mk_ctxt :: [Scaled ExpSigmaType] -> TcType -> TidyEnv -> TcM (TidyEnv, SDoc)+ mk_ctxt :: [Scaled ExpSigmaTypeFRR] -> TcType -> TidyEnv -> TcM (TidyEnv, SDoc) mk_ctxt arg_tys res_ty env = mkFunTysMsg env herald arg_tys' res_ty arity where@@ -372,7 +455,9 @@ reverse arg_tys -- this is safe b/c we're called from "go" -mkFunTysMsg :: TidyEnv -> SDoc -> [Scaled TcType] -> TcType -> Arity+mkFunTysMsg :: TidyEnv+ -> ExpectedFunTyOrigin+ -> [Scaled TcType] -> TcType -> Arity -> TcM (TidyEnv, SDoc) mkFunTysMsg env herald arg_tys res_ty n_val_args_in_call = do { (env', fun_rho) <- zonkTidyTcType env $@@ -391,7 +476,8 @@ ; return (env', msg) } where- full_herald = herald <+> speakNOf n_val_args_in_call (text "value argument")+ full_herald = pprExpectedFunTyHerald herald+ <+> speakNOf n_val_args_in_call (text "value argument") ---------------------- matchExpectedListTy :: TcRhoType -> TcM (TcCoercionN, TcRhoType)@@ -1479,9 +1565,9 @@ defer = unSwap swapped (uType_defer t_or_k origin) ty1 ty2 --- | Checks (TYVAR-TV) and (COERCION-HOLE) of Note [Unification preconditions];--- returns True if these conditions are satisfied. But see the Note for other--- preconditions, too.+-- | Checks (TYVAR-TV), (COERCION-HOLE) and (CONCRETE) of+-- Note [Unification preconditions]; returns True if these conditions+-- are satisfied. But see the Note for other preconditions, too. canSolveByUnification :: MetaInfo -> TcType -- zonked -> Bool canSolveByUnification _ xi@@ -1490,15 +1576,18 @@ canSolveByUnification info xi = case info of CycleBreakerTv -> False- TyVarTv -> case tcGetTyVar_maybe xi of- Nothing -> False- Just tv -> case tcTyVarDetails tv of -- (TYVAR-TV) wrinkle- MetaTv { mtv_info = info }- -> case info of- TyVarTv -> True- _ -> False- SkolemTv {} -> True- RuntimeUnk -> True+ ConcreteTv -> isConcrete xi -- (CONCRETE) check+ TyVarTv ->+ case tcGetTyVar_maybe xi of+ Nothing -> False+ Just tv ->+ case tcTyVarDetails tv of -- (TYVAR-TV) wrinkle+ SkolemTv {} -> True+ RuntimeUnk -> True+ MetaTv { mtv_info = info } ->+ case info of+ TyVarTv -> True+ _ -> False _ -> True swapOverTyVars :: Bool -> TcTyVar -> TcTyVar -> Bool@@ -1541,8 +1630,9 @@ MetaTv { mtv_info = info } -> case info of CycleBreakerTv -> 0 TyVarTv -> 1- TauTv -> 2- RuntimeUnkTv -> 3+ ConcreteTv -> 2+ TauTv -> 3+ RuntimeUnkTv -> 4 {- Note [Unification preconditions] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -1552,7 +1642,7 @@ This note only applied to /homogeneous/ equalities, in which both sides have the same kind. -There are four reasons not to unify:+There are five reasons not to unify: 1. (SKOL-ESC) Skolem-escape Consider the constraint@@ -1590,7 +1680,16 @@ * CycleBreakerTv: never unified, except by restoreTyVarCycles. -4. (COERCION-HOLE) Confusing coercion holes+4. (CONCRETE) A ConcreteTv can only unify with a concrete type,+ by definition.++ That is, if we have `rr[conc] ~ F Int`, we can't unify+ `rr` with `F Int`, so we hold off on unifying.+ Note however that the equality might get rewritten; for instance+ if we can rewrite `F Int` to a concrete type, say `FloatRep`,+ then we will have `rr[conc] ~ FloatRep` and we can unify `rr ~ FloatRep`.++5. (COERCION-HOLE) Confusing coercion holes Suppose our equality is (alpha :: k) ~ (Int |> {co}) where co :: Type ~ k is an unsolved wanted. Note that this@@ -1605,6 +1704,7 @@ This is expanded as Wrinkle (2) in Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Canonical. + Needless to say, all there are wrinkles: * (SKOL-ESC) Promotion. Given alpha[n] ~ ty, what if beta[k] is free@@ -1678,12 +1778,16 @@ a TyVarTv with a TauTv, because then the TyVarTv could (transitively) get a non-tyvar type. So give these a low priority: 1. + - ConcreteTv: These are like TauTv, except they can only unify with+ a concrete type. So we want to be able to write to them, but not quite+ as much as TauTvs: 2.+ - TauTv: This is the common case; we want these on the left so that they- can be written to: 2.+ can be written to: 3. - RuntimeUnkTv: These aren't really meta-variables used in type inference, but just a convenience in the implementation of the GHCi debugger.- Eagerly write to these: 3. See Note [RuntimeUnkTv] in+ Eagerly write to these: 4. See Note [RuntimeUnkTv] in GHC.Runtime.Heap.Inspect. * Names. If the level and priority comparisons are all
compiler/GHC/Tc/Utils/Zonk.hs view
@@ -561,12 +561,12 @@ , fun_matches = new_ms , fun_ext = new_co_fn }) } -zonk_bind env (AbsBinds { abs_tvs = tyvars, abs_ev_vars = evs- , abs_ev_binds = ev_binds- , abs_exports = exports- , abs_binds = val_binds- , abs_sig = has_sig })- = assert (all isImmutableTyVar tyvars) $+zonk_bind env (XHsBindsLR (AbsBinds { abs_tvs = tyvars, abs_ev_vars = evs+ , abs_ev_binds = ev_binds+ , abs_exports = exports+ , abs_binds = val_binds+ , abs_sig = has_sig }))+ = assert ( all isImmutableTyVar tyvars ) $ do { (env0, new_tyvars) <- zonkTyBndrsX env tyvars ; (env1, new_evs) <- zonkEvBndrsX env0 evs ; (env2, new_ev_binds) <- zonkTcEvBinds_s env1 ev_binds@@ -576,11 +576,11 @@ ; new_val_binds <- mapBagM (zonk_val_bind env3) val_binds ; new_exports <- mapM (zonk_export env3) exports ; return (new_val_binds, new_exports) }- ; return (AbsBinds { abs_ext = noExtField- , abs_tvs = new_tyvars, abs_ev_vars = new_evs+ ; return $ XHsBindsLR $+ AbsBinds { abs_tvs = new_tyvars, abs_ev_vars = new_evs , abs_ev_binds = new_ev_binds , abs_exports = new_exports, abs_binds = new_val_bind- , abs_sig = has_sig }) }+ , abs_sig = has_sig } } where zonk_val_bind env lbind | has_sig@@ -599,17 +599,15 @@ | otherwise = zonk_lbind env lbind -- The normal case - zonk_export :: ZonkEnv -> ABExport GhcTc -> TcM (ABExport GhcTc)- zonk_export env (ABE{ abe_ext = x- , abe_wrap = wrap+ zonk_export :: ZonkEnv -> ABExport -> TcM ABExport+ zonk_export env (ABE{ abe_wrap = wrap , abe_poly = poly_id , abe_mono = mono_id , abe_prags = prags }) = do new_poly_id <- zonkIdBndr env poly_id (_, new_wrap) <- zonkCoFn env wrap new_prags <- zonkSpecPrags env prags- return (ABE{ abe_ext = x- , abe_wrap = new_wrap+ return (ABE{ abe_wrap = new_wrap , abe_poly = new_poly_id , abe_mono = zonkIdOcc env mono_id , abe_prags = new_prags })@@ -780,21 +778,11 @@ return (HsAppType new_ty new_e t) -- NB: the type is an HsType; can't zonk that! -zonkExpr _ (HsRnBracketOut x _ _) = dataConCantHappen x--zonkExpr env (HsTcBracketOut ty wrap body bs)- = do wrap' <- traverse zonkQuoteWrap wrap- bs' <- mapM (zonk_b env) bs- new_ty <- zonkTcTypeToTypeX env ty- return (HsTcBracketOut new_ty wrap' body bs')- where- zonkQuoteWrap (QuoteWrapper ev ty) = do- let ev' = zonkIdOcc env ev- ty' <- zonkTcTypeToTypeX env ty- return (QuoteWrapper ev' ty')+zonkExpr env (HsTypedBracket hsb_tc body)+ = (\x -> HsTypedBracket x body) <$> zonkBracket env hsb_tc - zonk_b env' (PendingTcSplice n e) = do e' <- zonkLExpr env' e- return (PendingTcSplice n e')+zonkExpr env (HsUntypedBracket hsb_tc body)+ = (\x -> HsUntypedBracket x body) <$> zonkBracket env hsb_tc zonkExpr env (HsSpliceE _ (XSplice (HsSplicedT s))) = runTopSplice s >>= zonkExpr env@@ -1091,6 +1079,22 @@ , ol_type = ty' } }) } -------------------------------------------------------------------------+zonkBracket :: ZonkEnv -> HsBracketTc -> TcM HsBracketTc+zonkBracket env (HsBracketTc hsb_thing ty wrap bs)+ = do wrap' <- traverse zonkQuoteWrap wrap+ bs' <- mapM (zonk_b env) bs+ new_ty <- zonkTcTypeToTypeX env ty+ return (HsBracketTc hsb_thing new_ty wrap' bs')+ where+ zonkQuoteWrap (QuoteWrapper ev ty) = do+ let ev' = zonkIdOcc env ev+ ty' <- zonkTcTypeToTypeX env ty+ return (QuoteWrapper ev' ty')++ zonk_b env' (PendingTcSplice n e) = do e' <- zonkLExpr env' e+ return (PendingTcSplice n e')++------------------------------------------------------------------------- zonkArithSeq :: ZonkEnv -> ArithSeqInfo GhcTc -> TcM (ArithSeqInfo GhcTc) zonkArithSeq env (From e)@@ -1112,7 +1116,6 @@ new_e2 <- zonkLExpr env e2 new_e3 <- zonkLExpr env e3 return (FromThenTo new_e1 new_e2 new_e3)- ------------------------------------------------------------------------- zonkStmts :: Anno (StmtLR GhcTc GhcTc (LocatedA (body GhcTc))) ~ SrcSpanAnnA
compiler/GHC/Tc/Validity.hs view
@@ -1137,7 +1137,9 @@ -- but here we want to treat them as equalities = -- Equational constraints are valid in all contexts, and -- we do not need to check e.g. for FlexibleContexts here, so just do nothing- return ()+ -- We used to require TypeFamilies/GADTs for equality constraints,+ -- but not anymore (GHC Proposal #371)+ return () | isIPClass cls = do { check_arity@@ -1788,7 +1790,6 @@ check foralld_tvs pred = case classifyPredType pred of EqPred {} -> return () -- See #4200.- SpecialPred {} -> return () IrredPred {} -> check2 foralld_tvs pred (sizeType pred) ClassPred cls tys | isTerminatingClass cls@@ -1807,6 +1808,10 @@ -> check (foralld_tvs `extendVarSetList` tvs) head_pred' -- Termination of the quantified predicate itself is checked -- when the predicates are individually checked for validity+ SpecialPred {} ->+ pprPanic "checkInstTermination: unexpected special constraint" $+ vcat [ text "pred:" <+> ppr pred+ , text "theta:" <+> ppr theta ] check2 foralld_tvs pred pred_size | not (null bad_tvs) = failWithTc $ TcRnUnknownMessage $ mkPlainError noHints $
compiler/GHC/ThToHs.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-}@@ -96,9 +97,8 @@ -- Reason: so a (head []) in TH code doesn't subsequently -- make GHC crash when it tries to walk the generated tree --- Use the loc everywhere, for lack of anything better--- In particular, we want it on binding locations, so that variables bound in--- the spliced-in declarations get a location that at least relates to the splice point+-- Use the SrcSpan everywhere, for lack of anything better.+-- See Note [Source locations within TH splices]. instance Applicative CvtM where pure x = CvtM $ \_ loc -> Right (loc,x)@@ -124,16 +124,18 @@ getL :: CvtM SrcSpan getL = CvtM (\_ loc -> Right (loc,loc)) +-- NB: This is only used in conjunction with LineP pragmas.+-- See Note [Source locations within TH splices]. setL :: SrcSpan -> CvtM () setL loc = CvtM (\_ _ -> Right (loc, ())) -returnLA :: e -> CvtM (GenLocated (SrcSpanAnn' (EpAnn ann)) e)+returnLA :: e -> CvtM (LocatedAn ann e) returnLA x = CvtM (\_ loc -> Right (loc, L (noAnnSrcSpan loc) x)) returnJustLA :: a -> CvtM (Maybe (LocatedA a)) returnJustLA = fmap Just . returnLA -wrapParLA :: (LocatedA a -> a) -> a -> CvtM a+wrapParLA :: (LocatedAn ann a -> b) -> a -> CvtM b wrapParLA add_par x = CvtM (\_ loc -> Right (loc, add_par (L (noAnnSrcSpan loc) x))) wrapMsg :: (Show a, TH.Ppr a) => String -> a -> CvtM b -> CvtM b@@ -165,6 +167,41 @@ Left err -> Left err Right (loc', v) -> Right (loc', L (noAnnSrcSpan loc) v) +{-+Note [Source locations within TH splices]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider a TH splice such as $(x), where `x` evaluates to `id True`. What+source locations should we use for subexpressions within the splice, such as+`id` and `True`? We basically have two options:++1. Don't give anything within the splice a SrcSpan. That is, use the `noLoc`+ everywhere.+2. Give everything within the splice the same `SrcSpan` as where the splice+ occurs (i.e., where $(x) occurs).++We implement option (2) for the following reasons:++* We want SrcSpans on binding locations so that variables bound in the+ spliced-in declarations get a location that at least relates to the splice+ point.++* Generally speaking, having *some* SrcSpan for each sub-expression in the AST+ in better than having no SrcSpan at all. This extra information can be useful+ for programs that walk over the AST directly.++Because of our choice of option (2), we are very careful not to use the noLoc+function anywhere in GHC.ThToHs. Instead, we thread around a SrcSpan in CvtM+and allow retrieving the SrcSpan through combinators such as getL, returnLA,+wrapParLA, etc.++Note that CvtM is actually a *state* monad vis-à-vis SrcSpan, not just a+reader monad. This is because LineP pragmas can change the source location+within a splice—see testsuite/tests/th/TH_linePragma.hs for an example. This+is a bit unusual, since it changes the source location from that of the splice+point to that of the code being spliced in. Nevertheless, LineP is *the* reason+why CvtM is a state monad.+-}+ ------------------------------------------------------------------- cvtDecs :: [TH.Dec] -> CvtM [LHsDecl GhcPs] cvtDecs = fmap catMaybes . mapM cvtDec@@ -394,7 +431,7 @@ cvtDec (TH.RoleAnnotD tc roles) = do { tc' <- tconNameN tc- ; let roles' = map (noLocA . cvtRole) roles+ ; roles' <- traverse (returnLA . cvtRole) roles ; returnJustLA $ Hs.RoleAnnotD noExtField (RoleAnnotDecl noAnn tc' roles') } @@ -437,7 +474,7 @@ cvtDir n (ExplBidir cls) = do { ms <- mapM (cvtClause (mkPrefixFunRhs n)) cls ; th_origin <- getOrigin- ; return $ ExplicitBidirectional $ mkMatchGroup th_origin (noLocA ms) }+ ; wrapParLA (ExplicitBidirectional . mkMatchGroup th_origin) ms } cvtDec (TH.PatSynSigD nm ty) = do { nm' <- cNameN nm@@ -599,8 +636,8 @@ cvtConstr (RecC c varstrtys) = do { c' <- cNameN c ; args' <- mapM cvt_id_arg varstrtys- ; returnLA $ mkConDeclH98 noAnn c' Nothing Nothing- (RecCon (noLocA args')) }+ ; con_decl <- wrapParLA (mkConDeclH98 noAnn c' Nothing Nothing . RecCon) args'+ ; returnLA con_decl } cvtConstr (InfixC st1 c st2) = do { c' <- cNameN c@@ -647,7 +684,7 @@ = do { c' <- mapM cNameN c ; args <- mapM cvt_arg strtys ; ty' <- cvtType ty- ; returnLA $ mk_gadt_decl c' (PrefixConGADT $ map hsLinear args) ty'}+ ; mk_gadt_decl c' (PrefixConGADT $ map hsLinear args) ty'} cvtConstr (RecGadtC [] _varstrtys _ty) = failWith (text "RecGadtC must have at least one constructor name")@@ -656,18 +693,21 @@ = do { c' <- mapM cNameN c ; ty' <- cvtType ty ; rec_flds <- mapM cvt_id_arg varstrtys- ; returnLA $ mk_gadt_decl c' (RecConGADT (noLocA rec_flds) noHsUniTok) ty' }+ ; lrec_flds <- returnLA rec_flds+ ; mk_gadt_decl c' (RecConGADT lrec_flds noHsUniTok) ty' } mk_gadt_decl :: [LocatedN RdrName] -> HsConDeclGADTDetails GhcPs -> LHsType GhcPs- -> ConDecl GhcPs+ -> CvtM (LConDecl GhcPs) mk_gadt_decl names args res_ty- = ConDeclGADT { con_g_ext = noAnn- , con_names = names- , con_bndrs = noLocA mkHsOuterImplicit- , con_mb_cxt = Nothing- , con_g_args = args- , con_res_ty = res_ty- , con_doc = Nothing }+ = do bndrs <- returnLA mkHsOuterImplicit+ returnLA $ ConDeclGADT+ { con_g_ext = noAnn+ , con_names = names+ , con_bndrs = bndrs+ , con_mb_cxt = Nothing+ , con_g_args = args+ , con_res_ty = res_ty+ , con_doc = Nothing } cvtSrcUnpackedness :: TH.SourceUnpackedness -> SrcUnpackedness cvtSrcUnpackedness NoSourceUnpackedness = NoSrcUnpack@@ -691,12 +731,12 @@ cvt_id_arg (i, str, ty) = do { L li i' <- vNameN i ; ty' <- cvt_arg (str,ty)- ; return $ noLocA (ConDeclField+ ; returnLA $ ConDeclField { cd_fld_ext = noAnn , cd_fld_names = [L (l2l li) $ FieldOcc noExtField (L li i')] , cd_fld_type = ty'- , cd_fld_doc = Nothing}) }+ , cd_fld_doc = Nothing} } cvtDerivs :: [TH.DerivClause] -> CvtM (HsDeriving GhcPs) cvtDerivs cs = do { mapM cvtDerivClause cs }@@ -712,21 +752,22 @@ ------------------------------------------ cvtForD :: Foreign -> CvtM (ForeignDecl GhcPs)-cvtForD (ImportF callconv safety from nm ty)- -- the prim and javascript calling conventions do not support headers- -- and are inserted verbatim, analogous to mkImport in GHC.Parser.PostProcess- | callconv == TH.Prim || callconv == TH.JavaScript- = mk_imp (CImport (noLoc (cvt_conv callconv)) (noLoc safety') Nothing- (CFunction (StaticTarget (SourceText from)- (mkFastString from) Nothing- True))- (noLoc $ quotedSourceText from))- | Just impspec <- parseCImport (noLoc (cvt_conv callconv)) (noLoc safety')- (mkFastString (TH.nameBase nm))- from (noLoc $ quotedSourceText from)- = mk_imp impspec- | otherwise- = failWith $ text (show from) <+> text "is not a valid ccall impent"+cvtForD (ImportF callconv safety from nm ty) =+ do { l <- getL+ ; if -- the prim and javascript calling conventions do not support headers+ -- and are inserted verbatim, analogous to mkImport in GHC.Parser.PostProcess+ | callconv == TH.Prim || callconv == TH.JavaScript+ -> mk_imp (CImport (L l (cvt_conv callconv)) (L l safety') Nothing+ (CFunction (StaticTarget (SourceText from)+ (mkFastString from) Nothing+ True))+ (L l $ quotedSourceText from))+ | Just impspec <- parseCImport (L l (cvt_conv callconv)) (L l safety')+ (mkFastString (TH.nameBase nm))+ from (L l $ quotedSourceText from)+ -> mk_imp impspec+ | otherwise+ -> failWith $ text (show from) <+> text "is not a valid ccall impent" } where mk_imp impspec = do { nm' <- vNameN nm@@ -744,10 +785,11 @@ cvtForD (ExportF callconv as nm ty) = do { nm' <- vNameN nm ; ty' <- cvtSigType ty- ; let e = CExport (noLoc (CExportStatic (SourceText as)- (mkFastString as)- (cvt_conv callconv)))- (noLoc (SourceText as))+ ; l <- getL+ ; let e = CExport (L l (CExportStatic (SourceText as)+ (mkFastString as)+ (cvt_conv callconv)))+ (L l (SourceText as)) ; return $ ForeignExport { fd_e_ext = noAnn , fd_name = nm' , fd_sig_ty = ty'@@ -780,6 +822,17 @@ toSrcTxt a = SourceText $ src a ; returnJustLA $ Hs.SigD noExtField $ InlineSig noAnn nm' ip } +cvtPragmaD (OpaqueP nm)+ = do { nm' <- vNameN nm+ ; let ip = InlinePragma { inl_src = srcTxt+ , inl_inline = Opaque srcTxt+ , inl_rule = Hs.FunLike+ , inl_act = NeverActive+ , inl_sat = Nothing }+ where+ srcTxt = SourceText "{-# OPAQUE"+ ; returnJustLA $ Hs.SigD noExtField $ InlineSig noAnn nm' ip }+ cvtPragmaD (SpecialiseP nm ty inline phases) = do { nm' <- vNameN nm ; ty' <- cvtSigType ty@@ -807,22 +860,24 @@ cvtPragmaD (RuleP nm ty_bndrs tm_bndrs lhs rhs phases) = do { let nm' = mkFastString nm+ ; rd_name' <- returnLA (quotedSourceText nm,nm') ; let act = cvtPhases phases AlwaysActive ; ty_bndrs' <- traverse cvtTvs ty_bndrs ; tm_bndrs' <- mapM cvtRuleBndr tm_bndrs ; lhs' <- cvtl lhs ; rhs' <- cvtl rhs+ ; rule <- returnLA $+ HsRule { rd_ext = noAnn+ , rd_name = rd_name'+ , rd_act = act+ , rd_tyvs = ty_bndrs'+ , rd_tmvs = tm_bndrs'+ , rd_lhs = lhs'+ , rd_rhs = rhs' } ; returnJustLA $ Hs.RuleD noExtField $ HsRules { rds_ext = noAnn , rds_src = SourceText "{-# RULES"- , rds_rules = [noLocA $- HsRule { rd_ext = noAnn- , rd_name = (noLocA (quotedSourceText nm,nm'))- , rd_act = act- , rd_tyvs = ty_bndrs'- , rd_tmvs = tm_bndrs'- , rd_lhs = lhs'- , rd_rhs = rhs' }] }+ , rds_rules = [rule] } } @@ -832,20 +887,22 @@ ModuleAnnotation -> return ModuleAnnProvenance TypeAnnotation n -> do n' <- tconName n- return (TypeAnnProvenance (noLocA n'))+ wrapParLA TypeAnnProvenance n' ValueAnnotation n -> do n' <- vcName n- return (ValueAnnProvenance (noLocA n'))+ wrapParLA ValueAnnProvenance n' ; returnJustLA $ Hs.AnnD noExtField $ HsAnnotation noAnn (SourceText "{-# ANN") target' exp' } +-- NB: This is the only place in GHC.ThToHs that makes use of the `setL`+-- function. See Note [Source locations within TH splices]. cvtPragmaD (LineP line file) = do { setL (srcLocSpan (mkSrcLoc (fsLit file) line 1)) ; return Nothing } cvtPragmaD (CompleteP cls mty)- = do { cls' <- noLoc <$> mapM cNameN cls+ = do { cls' <- wrapL $ mapM cNameN cls ; mty' <- traverse tconNameN mty ; returnJustLA $ Hs.SigD noExtField $ CompleteMatchSig noAnn NoSourceText cls' mty' }@@ -871,11 +928,11 @@ cvtRuleBndr :: TH.RuleBndr -> CvtM (Hs.LRuleBndr GhcPs) cvtRuleBndr (RuleVar n) = do { n' <- vNameN n- ; return $ noLocA $ Hs.RuleBndr noAnn n' }+ ; returnLA $ Hs.RuleBndr noAnn n' } cvtRuleBndr (TypedRuleVar n ty) = do { n' <- vNameN n ; ty' <- cvtType ty- ; return $ noLocA $ Hs.RuleBndrSig noAnn n' $ mkHsPatSigType noAnn ty' }+ ; returnLA $ Hs.RuleBndrSig noAnn n' $ mkHsPatSigType noAnn ty' } --------------------------------------------------- -- Declarations@@ -919,8 +976,8 @@ cvtl :: TH.Exp -> CvtM (LHsExpr GhcPs) cvtl e = wrapLA (cvt e) where- cvt (VarE s) = do { s' <- vName s; return $ HsVar noExtField (noLocA s') }- cvt (ConE s) = do { s' <- cName s; return $ HsVar noExtField (noLocA s') }+ cvt (VarE s) = do { s' <- vName s; wrapParLA (HsVar noExtField) s' }+ cvt (ConE s) = do { s' <- cName s; wrapParLA (HsVar noExtField) s' } cvt (LitE l) | overloadedLit l = go cvtOverLit (HsOverLit noComments) (hsOverLitNeedsParens appPrec)@@ -934,7 +991,7 @@ go cvt_lit mk_expr is_compound_lit = do l' <- cvt_lit l let e' = mk_expr l'- return $ if is_compound_lit l' then gHsPar (noLocA e') else e'+ if is_compound_lit l' then wrapParLA gHsPar e' else pure e' cvt (AppE x@(LamE _ _) y) = do { x' <- cvtl x; y' <- cvtl y ; return $ HsApp noComments (mkLHsPar x') (mkLHsPar y')}@@ -953,13 +1010,11 @@ cvt (LamE ps e) = do { ps' <- cvtPats ps; e' <- cvtl e ; let pats = map (parenthesizePat appPrec) ps' ; th_origin <- getOrigin- ; return $ HsLam noExtField (mkMatchGroup th_origin- (noLocA [mkSimpleMatch LambdaExpr- pats e']))}+ ; wrapParLA (HsLam noExtField . mkMatchGroup th_origin)+ [mkSimpleMatch LambdaExpr pats e']} cvt (LamCaseE ms) = do { ms' <- mapM (cvtMatch CaseAlt) ms ; th_origin <- getOrigin- ; return $ HsLamCase noAnn- (mkMatchGroup th_origin (noLocA ms'))+ ; wrapParLA (HsLamCase noAnn . mkMatchGroup th_origin) ms' } cvt (TupE es) = cvt_tup es Boxed cvt (UnboxedTupE es) = cvt_tup es Unboxed@@ -977,8 +1032,7 @@ ; e' <- cvtl e; return $ HsLet noAnn noHsTok ds' noHsTok e'} cvt (CaseE e ms) = do { e' <- cvtl e; ms' <- mapM (cvtMatch CaseAlt) ms ; th_origin <- getOrigin- ; return $ HsCase noAnn e'- (mkMatchGroup th_origin (noLocA ms')) }+ ; wrapParLA (HsCase noAnn e' . mkMatchGroup th_origin) ms' } cvt (DoE m ss) = cvtHsDo (DoExpr (mk_mod <$> m)) ss cvt (MDoE m ss) = cvtHsDo (MDoExpr (mk_mod <$> m)) ss cvt (CompE ss) = cvtHsDo ListComp ss@@ -1033,11 +1087,11 @@ ; let pe = parenthesizeHsExpr sigPrec e' ; return $ ExprWithTySig noAnn pe (mkHsWildCardBndrs t') } cvt (RecConE c flds) = do { c' <- cNameN c- ; flds' <- mapM (cvtFld (mkFieldOcc . noLocA)) flds+ ; flds' <- mapM (cvtFld (wrapParLA mkFieldOcc)) flds ; return $ mkRdrRecordCon c' (HsRecFields flds' Nothing) noAnn } cvt (RecUpdE e flds) = do { e' <- cvtl e ; flds'- <- mapM (cvtFld (mkAmbiguousFieldOcc . noLocA))+ <- mapM (cvtFld (wrapParLA mkAmbiguousFieldOcc)) flds ; return $ RecordUpd noAnn e' (Left flds') } cvt (StaticE e) = fmap (HsStatic noAnn) $ cvtl e@@ -1045,7 +1099,7 @@ -- important, because UnboundVarE may contain -- constructor names - see #14627. { s' <- vcName s- ; return $ HsVar noExtField (noLocA s') }+ ; wrapParLA (HsVar noExtField) s' } cvt (LabelE s) = return $ HsOverLabel noComments (fsLit s) cvt (ImplicitParamVarE n) = do { n' <- ipName n; return $ HsIPVar noComments n' } cvt (GetFieldE exp f) = do { e' <- cvtl exp@@ -1085,14 +1139,16 @@ which we don't want. -} -cvtFld :: (RdrName -> t) -> (TH.Name, TH.Exp)+cvtFld :: (RdrName -> CvtM t) -> (TH.Name, TH.Exp) -> CvtM (LHsFieldBind GhcPs (LocatedAn NoEpAnns t) (LHsExpr GhcPs)) cvtFld f (v,e)- = do { v' <- vNameL v; e' <- cvtl e- ; return (noLocA $ HsFieldBind { hfbAnn = noAnn- , hfbLHS = la2la $ fmap f v'- , hfbRHS = e'- , hfbPun = False}) }+ = do { v' <- vNameL v+ ; lhs' <- traverse f v'+ ; e' <- cvtl e+ ; returnLA $ HsFieldBind { hfbAnn = noAnn+ , hfbLHS = la2la lhs'+ , hfbRHS = e'+ , hfbPun = False} } cvtDD :: Range -> CvtM (ArithSeqInfo GhcPs) cvtDD (FromR x) = do { x' <- cvtl x; return $ From x' }@@ -1189,7 +1245,7 @@ -> return (L loc (mkLastStmt body)) _ -> failWith (bad_last last') - ; return $ HsDo noAnn do_or_lc (noLocA (stmts'' ++ [last''])) }+ ; wrapParLA (HsDo noAnn do_or_lc) (stmts'' ++ [last'']) } where bad_last stmt = vcat [ text "Illegal last statement of" <+> pprAHsDoFlavour do_or_lc <> colon , nest 2 $ Outputable.ppr stmt@@ -1208,7 +1264,9 @@ where cvt_one ds = do { ds' <- cvtStmts ds ; return (ParStmtBlock noExtField ds' undefined noSyntaxExpr) }-cvtStmt (TH.RecS ss) = do { ss' <- mapM cvtStmt ss; returnLA (mkRecStmt noAnn (noLocA ss')) }+cvtStmt (TH.RecS ss) = do { ss' <- mapM cvtStmt ss+ ; rec_stmt <- wrapParLA (mkRecStmt noAnn) ss'+ ; returnLA rec_stmt } cvtMatch :: HsMatchContext GhcPs -> TH.Match -> CvtM (Hs.LMatch GhcPs (LHsExpr GhcPs))@@ -1304,12 +1362,13 @@ cvtp :: TH.Pat -> CvtM (Hs.Pat GhcPs) cvtp (TH.LitP l) | overloadedLit l = do { l' <- cvtOverLit l- ; return (mkNPat (noLocA l') Nothing noAnn) }+ ; l'' <- returnLA l'+ ; return (mkNPat l'' Nothing noAnn) } -- Not right for negative patterns; -- need to think about that! | otherwise = do { l' <- cvtLit l; return $ Hs.LitPat noExtField l' } cvtp (TH.VarP s) = do { s' <- vName s- ; return $ Hs.VarPat noExtField (noLocA s') }+ ; wrapParLA (Hs.VarPat noExtField) s' } cvtp (TupP ps) = do { ps' <- cvtPats ps ; return $ TuplePat noAnn ps' Boxed } cvtp (UnboxedTupP ps) = do { ps' <- cvtPats ps@@ -1368,11 +1427,11 @@ cvtPatFld (s,p) = do { L ls s' <- vNameN s ; p' <- cvtPat p- ; return (noLocA $ HsFieldBind { hfbAnn = noAnn- , hfbLHS- = L (l2l ls) $ mkFieldOcc (L (l2l ls) s')- , hfbRHS = p'- , hfbPun = False}) }+ ; returnLA $ HsFieldBind { hfbAnn = noAnn+ , hfbLHS+ = L (l2l ls) $ mkFieldOcc (L (l2l ls) s')+ , hfbRHS = p'+ , hfbPun = False} } {- | @cvtOpAppP x op y@ converts @op@ and @y@ and produces the operator application @x `op` y@. The produced tree of infix patterns will be left-biased, provided @x@ is.@@ -1489,19 +1548,15 @@ , normals `lengthIs` n -- Saturated -> returnLA (HsTupleTy noAnn HsBoxedOrConstraintTuple normals) | otherwise- -> mk_apps- (HsTyVar noAnn NotPromoted- (noLocA (getRdrName (tupleTyCon Boxed n))))- tys'+ -> do { tuple_tc <- returnLA $ getRdrName $ tupleTyCon Boxed n+ ; mk_apps (HsTyVar noAnn NotPromoted tuple_tc) tys' } UnboxedTupleT n | Just normals <- m_normals , normals `lengthIs` n -- Saturated -> returnLA (HsTupleTy noAnn HsUnboxedTuple normals) | otherwise- -> mk_apps- (HsTyVar noAnn NotPromoted- (noLocA (getRdrName (tupleTyCon Unboxed n))))- tys'+ -> do { tuple_tc <- returnLA $ getRdrName $ tupleTyCon Unboxed n+ ; mk_apps (HsTyVar noAnn NotPromoted tuple_tc) tys' } UnboxedSumT n | n < 2 -> failWith $@@ -1512,9 +1567,8 @@ , normals `lengthIs` n -- Saturated -> returnLA (HsSumTy noAnn normals) | otherwise- -> mk_apps- (HsTyVar noAnn NotPromoted (noLocA (getRdrName (sumTyCon n))))- tys'+ -> do { sum_tc <- returnLA $ getRdrName $ sumTyCon n+ ; mk_apps (HsTyVar noAnn NotPromoted sum_tc) tys' } ArrowT | Just normals <- m_normals , [x',y'] <- normals -> do@@ -1527,9 +1581,8 @@ let y'' = parenthesizeHsType sigPrec y' returnLA (HsFunTy noAnn (HsUnrestrictedArrow noHsUniTok) x'' y'') | otherwise- -> mk_apps- (HsTyVar noAnn NotPromoted (noLocA (getRdrName unrestrictedFunTyCon)))- tys'+ -> do { fun_tc <- returnLA $ getRdrName unrestrictedFunTyCon+ ; mk_apps (HsTyVar noAnn NotPromoted fun_tc) tys' } MulArrowT | Just normals <- m_normals , [w',x',y'] <- normals -> do@@ -1543,23 +1596,22 @@ w'' = hsTypeToArrow w' returnLA (HsFunTy noAnn w'' x'' y'') | otherwise- -> mk_apps- (HsTyVar noAnn NotPromoted (noLocA (getRdrName funTyCon)))- tys'+ -> do { fun_tc <- returnLA $ getRdrName funTyCon+ ; mk_apps (HsTyVar noAnn NotPromoted fun_tc) tys' } ListT | Just normals <- m_normals , [x'] <- normals -> returnLA (HsListTy noAnn x') | otherwise- -> mk_apps- (HsTyVar noAnn NotPromoted (noLocA (getRdrName listTyCon)))- tys'+ -> do { list_tc <- returnLA $ getRdrName listTyCon+ ; mk_apps (HsTyVar noAnn NotPromoted list_tc) tys' } VarT nm -> do { nm' <- tNameN nm ; mk_apps (HsTyVar noAnn NotPromoted nm') tys' } ConT nm -> do { nm' <- tconName nm ; let prom = name_promotedness nm'- ; mk_apps (HsTyVar noAnn prom (noLocA nm')) tys'}+ ; lnm' <- returnLA nm'+ ; mk_apps (HsTyVar noAnn prom lnm') tys'} ForallT tvs cxt ty | null tys'@@ -1600,8 +1652,9 @@ ; t1' <- cvtType t1 ; t2' <- cvtType t2 ; let prom = name_promotedness s'+ ; ls' <- returnLA s' ; mk_apps- (HsTyVar noAnn prom (noLocA s'))+ (HsTyVar noAnn prom ls') ([HsValArg t1', HsValArg t2'] ++ tys') } @@ -1613,11 +1666,11 @@ } -- Note [Converting UInfix] PromotedInfixT t1 s t2- -> do { s' <- cName s+ -> do { s' <- cNameN s ; t1' <- cvtType t1 ; t2' <- cvtType t2 ; mk_apps- (HsTyVar noAnn IsPromoted (noLocA s'))+ (HsTyVar noAnn IsPromoted s') ([HsValArg t1', HsValArg t2'] ++ tys') } @@ -1633,9 +1686,8 @@ ; mk_apps (HsParTy noAnn t') tys' } - PromotedT nm -> do { nm' <- cName nm- ; mk_apps (HsTyVar noAnn IsPromoted- (noLocA nm'))+ PromotedT nm -> do { nm' <- cNameN nm+ ; mk_apps (HsTyVar noAnn IsPromoted nm') tys' } -- Promoted data constructor; hence cName @@ -1644,10 +1696,8 @@ , normals `lengthIs` n -- Saturated -> returnLA (HsExplicitTupleTy noAnn normals) | otherwise- -> mk_apps- (HsTyVar noAnn IsPromoted- (noLocA (getRdrName (tupleDataCon Boxed n))))- tys'+ -> do { tuple_tc <- returnLA $ getRdrName $ tupleDataCon Boxed n+ ; mk_apps (HsTyVar noAnn IsPromoted tuple_tc) tys' } PromotedNilT -> mk_apps (HsExplicitListTy noAnn IsPromoted []) tys'@@ -1658,35 +1708,31 @@ , [ty1, L _ (HsExplicitListTy _ ip tys2)] <- normals -> returnLA (HsExplicitListTy noAnn ip (ty1:tys2)) | otherwise- -> mk_apps- (HsTyVar noAnn IsPromoted (noLocA (getRdrName consDataCon)))- tys'+ -> do { cons_tc <- returnLA $ getRdrName consDataCon+ ; mk_apps (HsTyVar noAnn IsPromoted cons_tc) tys' } StarT- -> mk_apps- (HsTyVar noAnn NotPromoted- (noLocA (getRdrName liftedTypeKindTyCon)))- tys'+ -> do { type_tc <- returnLA $ getRdrName liftedTypeKindTyCon+ ; mk_apps (HsTyVar noAnn NotPromoted type_tc) tys' } ConstraintT- -> mk_apps- (HsTyVar noAnn NotPromoted- (noLocA (getRdrName constraintKindTyCon)))- tys'+ -> do { constraint_tc <- returnLA $ getRdrName constraintKindTyCon+ ; mk_apps (HsTyVar noAnn NotPromoted constraint_tc) tys' } EqualityT | Just normals <- m_normals , [x',y'] <- normals -> let px = parenthesizeHsType opPrec x' py = parenthesizeHsType opPrec y'- in returnLA (HsOpTy noExtField px (noLocA eqTyCon_RDR) py)+ in do { eq_tc <- returnLA eqTyCon_RDR+ ; returnLA (HsOpTy noExtField px eq_tc py) } -- The long-term goal is to remove the above case entirely and -- subsume it under the case for InfixT. See #15815, comment:6, -- for more details. | otherwise ->- mk_apps (HsTyVar noAnn NotPromoted- (noLocA eqTyCon_RDR)) tys'+ do { eq_tc <- returnLA eqTyCon_RDR+ ; mk_apps (HsTyVar noAnn NotPromoted eq_tc) tys' } ImplicitParamT n t -> do { n' <- wrapL $ ipName n ; t' <- cvtType t@@ -1840,22 +1886,21 @@ -- see Note [Pattern synonym type signatures and Template Haskell] cvtPatSynSigTy (ForallT univs reqs (ForallT exis provs ty)) | null exis, null provs = cvtSigType (ForallT univs reqs ty)- | null univs, null reqs = do { l' <- getL- ; let l = noAnnSrcSpan l'- ; ty' <- cvtType (ForallT exis provs ty)- ; return $ L l $ mkHsImplicitSigType- $ L l (HsQualTy { hst_ctxt = noLocA []- , hst_xqual = noExtField- , hst_body = ty' }) }- | null reqs = do { l' <- getL- ; let l'' = noAnnSrcSpan l'- ; univs' <- cvtTvs univs+ | null univs, null reqs = do { ty' <- cvtType (ForallT exis provs ty)+ ; ctxt' <- returnLA []+ ; cxtTy <- wrapParLA mkHsImplicitSigType $+ HsQualTy { hst_ctxt = ctxt'+ , hst_xqual = noExtField+ , hst_body = ty' }+ ; returnLA cxtTy }+ | null reqs = do { univs' <- cvtTvs univs ; ty' <- cvtType (ForallT exis provs ty)- ; let forTy = mkHsExplicitSigType noAnn univs' $ L l'' cxtTy- cxtTy = HsQualTy { hst_ctxt = noLocA []+ ; ctxt' <- returnLA []+ ; let cxtTy = HsQualTy { hst_ctxt = ctxt' , hst_xqual = noExtField , hst_body = ty' }- ; return $ L (noAnnSrcSpan l') forTy }+ ; forTy <- wrapParLA (mkHsExplicitSigType noAnn univs') cxtTy+ ; returnLA forTy } | otherwise = cvtSigType (ForallT univs reqs (ForallT exis provs ty)) cvtPatSynSigTy ty = cvtSigType ty
+ compiler/GHC/Types/Unique/MemoFun.hs view
@@ -0,0 +1,21 @@+module GHC.Types.Unique.MemoFun (memoiseUniqueFun) where++import GHC.Prelude+import GHC.Types.Unique+import GHC.Types.Unique.FM++import Data.IORef+import System.IO.Unsafe++memoiseUniqueFun :: Uniquable k => (k -> a) -> k -> a+memoiseUniqueFun fun = unsafePerformIO $ do+ ref <- newIORef emptyUFM+ return $ \k -> unsafePerformIO $ do+ m <- readIORef ref+ case lookupUFM m k of+ Just a -> return a+ Nothing -> do+ let !a = fun k+ !m' = addToUFM m k a+ writeIORef ref m'+ return a
compiler/ghc-llvm-version.h view
@@ -3,7 +3,7 @@ #define __GHC_LLVM_VERSION_H__ /* The maximum supported LLVM version number */-#define sUPPORTED_LLVM_VERSION_MAX (13)+#define sUPPORTED_LLVM_VERSION_MAX (14) /* The minimum supported LLVM version number */ #define sUPPORTED_LLVM_VERSION_MIN (9)
ghc-lib.cabal view
@@ -1,7 +1,7 @@ cabal-version: >=1.22 build-type: Simple name: ghc-lib-version: 0.20220301+version: 0.20220401 license: BSD3 license-file: LICENSE category: Development@@ -82,7 +82,7 @@ process >= 1 && < 1.7, rts, hpc == 0.6.*,- ghc-lib-parser == 0.20220301,+ ghc-lib-parser == 0.20220401, stm build-tools: alex >= 3.1, happy >= 1.19.4 other-extensions:@@ -123,6 +123,7 @@ MonoLocalBinds NoImplicitPrelude ScopedTypeVariables+ TypeOperators hs-source-dirs: ghc-lib/stage0/libraries/ghc-boot/build ghc-lib/stage0/compiler/build@@ -264,6 +265,7 @@ GHC.Hs.Binds, GHC.Hs.Decls, GHC.Hs.Doc,+ GHC.Hs.DocString, GHC.Hs.Dump, GHC.Hs.Expr, GHC.Hs.Extension,@@ -293,6 +295,7 @@ GHC.Parser.Errors.Basic, GHC.Parser.Errors.Ppr, GHC.Parser.Errors.Types,+ GHC.Parser.HaddockLex, GHC.Parser.Header, GHC.Parser.Lexer, GHC.Parser.PostProcess,@@ -488,6 +491,7 @@ GHC.Cmm.Graph GHC.Cmm.Info GHC.Cmm.Info.Build+ GHC.Cmm.InitFini GHC.Cmm.LRegSet GHC.Cmm.LayoutStack GHC.Cmm.Lexer@@ -615,6 +619,7 @@ GHC.Driver.Config.Stg.Pipeline GHC.Driver.Config.Stg.Ppr GHC.Driver.Config.StgToCmm+ GHC.Driver.Config.Tidy GHC.Driver.GenerateCgIPEStub GHC.Driver.Main GHC.Driver.Make@@ -681,6 +686,7 @@ GHC.Platform.Host GHC.Plugins GHC.Rename.Bind+ GHC.Rename.Doc GHC.Rename.Env GHC.Rename.Expr GHC.Rename.Fixity@@ -795,6 +801,7 @@ GHC.ThToHs GHC.Types.Name.Shape GHC.Types.TyThing.Ppr+ GHC.Types.Unique.MemoFun GHC.Unit.Finder GHC.Utils.Asm GHC.Utils.Monad.State.Lazy
ghc-lib/stage0/compiler/build/primop-primop-info.hs-incl view
@@ -325,37 +325,37 @@ primOpInfo FloatToDoubleOp = mkGenPrimOp (fsLit "float2Double#") [] [floatPrimTy] (doublePrimTy) primOpInfo FloatDecode_IntOp = mkGenPrimOp (fsLit "decodeFloat_Int#") [] [floatPrimTy] ((mkTupleTy Unboxed [intPrimTy, intPrimTy])) primOpInfo NewArrayOp = mkGenPrimOp (fsLit "newArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [intPrimTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableArrayPrimTy deltaTy levPolyAlphaTy]))-primOpInfo ReadArrayOp = mkGenPrimOp (fsLit "readArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))-primOpInfo WriteArrayOp = mkGenPrimOp (fsLit "writeArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo ReadArrayOp = mkGenPrimOp (fsLit "readArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))+primOpInfo WriteArrayOp = mkGenPrimOp (fsLit "writeArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo SizeofArrayOp = mkGenPrimOp (fsLit "sizeofArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec] [mkArrayPrimTy levPolyAlphaTy] (intPrimTy)-primOpInfo SizeofMutableArrayOp = mkGenPrimOp (fsLit "sizeofMutableArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy] (intPrimTy)+primOpInfo SizeofMutableArrayOp = mkGenPrimOp (fsLit "sizeofMutableArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy] (intPrimTy) primOpInfo IndexArrayOp = mkGenPrimOp (fsLit "indexArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec] [mkArrayPrimTy levPolyAlphaTy, intPrimTy] ((mkTupleTy Unboxed [levPolyAlphaTy]))-primOpInfo UnsafeFreezeArrayOp = mkGenPrimOp (fsLit "unsafeFreezeArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkArrayPrimTy levPolyAlphaTy]))+primOpInfo UnsafeFreezeArrayOp = mkGenPrimOp (fsLit "unsafeFreezeArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkArrayPrimTy levPolyAlphaTy])) primOpInfo UnsafeThawArrayOp = mkGenPrimOp (fsLit "unsafeThawArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [mkArrayPrimTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableArrayPrimTy deltaTy levPolyAlphaTy])) primOpInfo CopyArrayOp = mkGenPrimOp (fsLit "copyArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [mkArrayPrimTy levPolyAlphaTy, intPrimTy, mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)-primOpInfo CopyMutableArrayOp = mkGenPrimOp (fsLit "copyMutableArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo CopyMutableArrayOp = mkGenPrimOp (fsLit "copyMutableArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo CloneArrayOp = mkGenPrimOp (fsLit "cloneArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec] [mkArrayPrimTy levPolyAlphaTy, intPrimTy, intPrimTy] (mkArrayPrimTy levPolyAlphaTy)-primOpInfo CloneMutableArrayOp = mkGenPrimOp (fsLit "cloneMutableArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableArrayPrimTy deltaTy levPolyAlphaTy]))-primOpInfo FreezeArrayOp = mkGenPrimOp (fsLit "freezeArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkArrayPrimTy levPolyAlphaTy]))+primOpInfo CloneMutableArrayOp = mkGenPrimOp (fsLit "cloneMutableArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableArrayPrimTy deltaTy levPolyAlphaTy]))+primOpInfo FreezeArrayOp = mkGenPrimOp (fsLit "freezeArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkArrayPrimTy levPolyAlphaTy])) primOpInfo ThawArrayOp = mkGenPrimOp (fsLit "thawArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [mkArrayPrimTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableArrayPrimTy deltaTy levPolyAlphaTy]))-primOpInfo CasArrayOp = mkGenPrimOp (fsLit "casArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy]))+primOpInfo CasArrayOp = mkGenPrimOp (fsLit "casArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy])) primOpInfo NewSmallArrayOp = mkGenPrimOp (fsLit "newSmallArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [intPrimTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy]))-primOpInfo ShrinkSmallMutableArrayOp_Char = mkGenPrimOp (fsLit "shrinkSmallMutableArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)-primOpInfo ReadSmallArrayOp = mkGenPrimOp (fsLit "readSmallArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))-primOpInfo WriteSmallArrayOp = mkGenPrimOp (fsLit "writeSmallArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo ShrinkSmallMutableArrayOp_Char = mkGenPrimOp (fsLit "shrinkSmallMutableArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo ReadSmallArrayOp = mkGenPrimOp (fsLit "readSmallArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))+primOpInfo WriteSmallArrayOp = mkGenPrimOp (fsLit "writeSmallArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo SizeofSmallArrayOp = mkGenPrimOp (fsLit "sizeofSmallArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallArrayPrimTy levPolyAlphaTy] (intPrimTy)-primOpInfo SizeofSmallMutableArrayOp = mkGenPrimOp (fsLit "sizeofSmallMutableArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy] (intPrimTy)-primOpInfo GetSizeofSmallMutableArrayOp = mkGenPrimOp (fsLit "getSizeofSmallMutableArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))+primOpInfo SizeofSmallMutableArrayOp = mkGenPrimOp (fsLit "sizeofSmallMutableArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy] (intPrimTy)+primOpInfo GetSizeofSmallMutableArrayOp = mkGenPrimOp (fsLit "getSizeofSmallMutableArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy])) primOpInfo IndexSmallArrayOp = mkGenPrimOp (fsLit "indexSmallArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallArrayPrimTy levPolyAlphaTy, intPrimTy] ((mkTupleTy Unboxed [levPolyAlphaTy]))-primOpInfo UnsafeFreezeSmallArrayOp = mkGenPrimOp (fsLit "unsafeFreezeSmallArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallArrayPrimTy levPolyAlphaTy]))+primOpInfo UnsafeFreezeSmallArrayOp = mkGenPrimOp (fsLit "unsafeFreezeSmallArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallArrayPrimTy levPolyAlphaTy])) primOpInfo UnsafeThawSmallArrayOp = mkGenPrimOp (fsLit "unsafeThawSmallArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [mkSmallArrayPrimTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy])) primOpInfo CopySmallArrayOp = mkGenPrimOp (fsLit "copySmallArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [mkSmallArrayPrimTy levPolyAlphaTy, intPrimTy, mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)-primOpInfo CopySmallMutableArrayOp = mkGenPrimOp (fsLit "copySmallMutableArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo CopySmallMutableArrayOp = mkGenPrimOp (fsLit "copySmallMutableArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo CloneSmallArrayOp = mkGenPrimOp (fsLit "cloneSmallArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallArrayPrimTy levPolyAlphaTy, intPrimTy, intPrimTy] (mkSmallArrayPrimTy levPolyAlphaTy)-primOpInfo CloneSmallMutableArrayOp = mkGenPrimOp (fsLit "cloneSmallMutableArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy]))-primOpInfo FreezeSmallArrayOp = mkGenPrimOp (fsLit "freezeSmallArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallArrayPrimTy levPolyAlphaTy]))+primOpInfo CloneSmallMutableArrayOp = mkGenPrimOp (fsLit "cloneSmallMutableArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy]))+primOpInfo FreezeSmallArrayOp = mkGenPrimOp (fsLit "freezeSmallArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallArrayPrimTy levPolyAlphaTy])) primOpInfo ThawSmallArrayOp = mkGenPrimOp (fsLit "thawSmallArray#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [mkSmallArrayPrimTy levPolyAlphaTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy]))-primOpInfo CasSmallArrayOp = mkGenPrimOp (fsLit "casSmallArray#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy]))+primOpInfo CasSmallArrayOp = mkGenPrimOp (fsLit "casSmallArray#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkSmallMutableArrayPrimTy deltaTy levPolyAlphaTy, intPrimTy, levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy])) primOpInfo NewByteArrayOp_Char = mkGenPrimOp (fsLit "newByteArray#") [deltaTyVarSpec] [intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableByteArrayPrimTy deltaTy])) primOpInfo NewPinnedByteArrayOp_Char = mkGenPrimOp (fsLit "newPinnedByteArray#") [deltaTyVarSpec] [intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableByteArrayPrimTy deltaTy])) primOpInfo NewAlignedPinnedByteArrayOp_Char = mkGenPrimOp (fsLit "newAlignedPinnedByteArray#") [deltaTyVarSpec] [intPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableByteArrayPrimTy deltaTy]))@@ -555,14 +555,14 @@ primOpInfo AtomicReadAddrOp_Word = mkGenPrimOp (fsLit "atomicReadWordAddr#") [deltaTyVarSpec] [addrPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, wordPrimTy])) primOpInfo AtomicWriteAddrOp_Word = mkGenPrimOp (fsLit "atomicWriteWordAddr#") [deltaTyVarSpec] [addrPrimTy, wordPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo NewMutVarOp = mkGenPrimOp (fsLit "newMutVar#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutVarPrimTy deltaTy levPolyAlphaTy]))-primOpInfo ReadMutVarOp = mkGenPrimOp (fsLit "readMutVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))-primOpInfo WriteMutVarOp = mkGenPrimOp (fsLit "writeMutVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo ReadMutVarOp = mkGenPrimOp (fsLit "readMutVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))+primOpInfo WriteMutVarOp = mkGenPrimOp (fsLit "writeMutVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo AtomicModifyMutVar2Op = mkGenPrimOp (fsLit "atomicModifyMutVar2#") [deltaTyVarSpec, alphaTyVarSpec, gammaTyVarSpec] [mkMutVarPrimTy deltaTy alphaTy, (mkVisFunTyMany (alphaTy) (gammaTy)), mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, alphaTy, gammaTy])) primOpInfo AtomicModifyMutVar_Op = mkGenPrimOp (fsLit "atomicModifyMutVar_#") [deltaTyVarSpec, alphaTyVarSpec] [mkMutVarPrimTy deltaTy alphaTy, (mkVisFunTyMany (alphaTy) (alphaTy)), mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, alphaTy, alphaTy]))-primOpInfo CasMutVarOp = mkGenPrimOp (fsLit "casMutVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMutVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy]))-primOpInfo CatchOp = mkGenPrimOp (fsLit "catch#") [runtimeRep1TyVarInf, openAlphaTyVarSpec, levity2TyVarInf, levPolyBetaTyVarSpec] [(mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))), (mkVisFunTyMany (levPolyBetaTy) ((mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))-primOpInfo RaiseOp = mkGenPrimOp (fsLit "raise#") [levity1TyVarInf, levPolyAlphaTyVarSpec, runtimeRep2TyVarInf, openBetaTyVarSpec] [levPolyAlphaTy] (openBetaTy)-primOpInfo RaiseIOOp = mkGenPrimOp (fsLit "raiseIO#") [levity1TyVarInf, levPolyAlphaTyVarSpec, runtimeRep2TyVarInf, openBetaTyVarSpec] [levPolyAlphaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openBetaTy]))+primOpInfo CasMutVarOp = mkGenPrimOp (fsLit "casMutVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMutVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy]))+primOpInfo CatchOp = mkGenPrimOp (fsLit "catch#") [runtimeRep1TyVarInf, levity2TyVarInf, openAlphaTyVarSpec, levPolyBetaTyVarSpec] [(mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))), (mkVisFunTyMany (levPolyBetaTy) ((mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))+primOpInfo RaiseOp = mkGenPrimOp (fsLit "raise#") [levity1TyVarInf, runtimeRep2TyVarInf, levPolyAlphaTyVarSpec, openBetaTyVarSpec] [levPolyAlphaTy] (openBetaTy)+primOpInfo RaiseIOOp = mkGenPrimOp (fsLit "raiseIO#") [levity1TyVarInf, runtimeRep2TyVarInf, levPolyAlphaTyVarSpec, openBetaTyVarSpec] [levPolyAlphaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openBetaTy])) primOpInfo MaskAsyncExceptionsOp = mkGenPrimOp (fsLit "maskAsyncExceptions#") [runtimeRep1TyVarInf, openAlphaTyVarSpec] [(mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy])) primOpInfo MaskUninterruptibleOp = mkGenPrimOp (fsLit "maskUninterruptible#") [runtimeRep1TyVarInf, openAlphaTyVarSpec] [(mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy])) primOpInfo UnmaskAsyncExceptionsOp = mkGenPrimOp (fsLit "unmaskAsyncExceptions#") [runtimeRep1TyVarInf, openAlphaTyVarSpec] [(mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, openAlphaTy]))@@ -572,20 +572,20 @@ primOpInfo CatchRetryOp = mkGenPrimOp (fsLit "catchRetry#") [levity1TyVarInf, levPolyAlphaTyVarSpec] [(mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, levPolyAlphaTy]))), (mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, levPolyAlphaTy]))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, levPolyAlphaTy])) primOpInfo CatchSTMOp = mkGenPrimOp (fsLit "catchSTM#") [levity1TyVarInf, levPolyAlphaTyVarSpec, betaTyVarSpec] [(mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, levPolyAlphaTy]))), (mkVisFunTyMany (betaTy) ((mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, levPolyAlphaTy]))))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, levPolyAlphaTy])) primOpInfo NewTVarOp = mkGenPrimOp (fsLit "newTVar#") [levity1TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec] [levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkTVarPrimTy deltaTy levPolyAlphaTy]))-primOpInfo ReadTVarOp = mkGenPrimOp (fsLit "readTVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkTVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))-primOpInfo ReadTVarIOOp = mkGenPrimOp (fsLit "readTVarIO#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkTVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))-primOpInfo WriteTVarOp = mkGenPrimOp (fsLit "writeTVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkTVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)-primOpInfo NewMVarOp = mkGenPrimOp (fsLit "newMVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMVarPrimTy deltaTy levPolyAlphaTy]))-primOpInfo TakeMVarOp = mkGenPrimOp (fsLit "takeMVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))-primOpInfo TryTakeMVarOp = mkGenPrimOp (fsLit "tryTakeMVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy]))-primOpInfo PutMVarOp = mkGenPrimOp (fsLit "putMVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)-primOpInfo TryPutMVarOp = mkGenPrimOp (fsLit "tryPutMVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))-primOpInfo ReadMVarOp = mkGenPrimOp (fsLit "readMVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))-primOpInfo TryReadMVarOp = mkGenPrimOp (fsLit "tryReadMVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy]))-primOpInfo IsEmptyMVarOp = mkGenPrimOp (fsLit "isEmptyMVar#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))-primOpInfo NewIOPortOp = mkGenPrimOp (fsLit "newIOPort#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkIOPortPrimTy deltaTy levPolyAlphaTy]))-primOpInfo ReadIOPortOp = mkGenPrimOp (fsLit "readIOPort#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkIOPortPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))-primOpInfo WriteIOPortOp = mkGenPrimOp (fsLit "writeIOPort#") [deltaTyVarSpec, levity1TyVarInf, levPolyAlphaTyVarSpec] [mkIOPortPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))+primOpInfo ReadTVarOp = mkGenPrimOp (fsLit "readTVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkTVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))+primOpInfo ReadTVarIOOp = mkGenPrimOp (fsLit "readTVarIO#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkTVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))+primOpInfo WriteTVarOp = mkGenPrimOp (fsLit "writeTVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkTVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo NewMVarOp = mkGenPrimOp (fsLit "newMVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMVarPrimTy deltaTy levPolyAlphaTy]))+primOpInfo TakeMVarOp = mkGenPrimOp (fsLit "takeMVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))+primOpInfo TryTakeMVarOp = mkGenPrimOp (fsLit "tryTakeMVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy]))+primOpInfo PutMVarOp = mkGenPrimOp (fsLit "putMVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo TryPutMVarOp = mkGenPrimOp (fsLit "tryPutMVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))+primOpInfo ReadMVarOp = mkGenPrimOp (fsLit "readMVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))+primOpInfo TryReadMVarOp = mkGenPrimOp (fsLit "tryReadMVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, levPolyAlphaTy]))+primOpInfo IsEmptyMVarOp = mkGenPrimOp (fsLit "isEmptyMVar#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkMVarPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))+primOpInfo NewIOPortOp = mkGenPrimOp (fsLit "newIOPort#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkIOPortPrimTy deltaTy levPolyAlphaTy]))+primOpInfo ReadIOPortOp = mkGenPrimOp (fsLit "readIOPort#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkIOPortPrimTy deltaTy levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, levPolyAlphaTy]))+primOpInfo WriteIOPortOp = mkGenPrimOp (fsLit "writeIOPort#") [levity1TyVarInf, deltaTyVarSpec, levPolyAlphaTyVarSpec] [mkIOPortPrimTy deltaTy levPolyAlphaTy, levPolyAlphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy])) primOpInfo DelayOp = mkGenPrimOp (fsLit "delay#") [deltaTyVarSpec] [intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo WaitReadOp = mkGenPrimOp (fsLit "waitRead#") [deltaTyVarSpec] [intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo WaitWriteOp = mkGenPrimOp (fsLit "waitWrite#") [deltaTyVarSpec] [intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)@@ -598,8 +598,8 @@ primOpInfo IsCurrentThreadBoundOp = mkGenPrimOp (fsLit "isCurrentThreadBound#") [] [mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, intPrimTy])) primOpInfo NoDuplicateOp = mkGenPrimOp (fsLit "noDuplicate#") [deltaTyVarSpec] [mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo ThreadStatusOp = mkGenPrimOp (fsLit "threadStatus#") [] [threadIdPrimTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, intPrimTy, intPrimTy, intPrimTy]))-primOpInfo MkWeakOp = mkGenPrimOp (fsLit "mkWeak#") [levity1TyVarInf, levPolyAlphaTyVarSpec, levity2TyVarInf, levPolyBetaTyVarSpec, gammaTyVarSpec] [levPolyAlphaTy, levPolyBetaTy, (mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, gammaTy]))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, mkWeakPrimTy levPolyBetaTy]))-primOpInfo MkWeakNoFinalizerOp = mkGenPrimOp (fsLit "mkWeakNoFinalizer#") [levity1TyVarInf, levPolyAlphaTyVarSpec, levity2TyVarInf, levPolyBetaTyVarSpec] [levPolyAlphaTy, levPolyBetaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, mkWeakPrimTy levPolyBetaTy]))+primOpInfo MkWeakOp = mkGenPrimOp (fsLit "mkWeak#") [levity1TyVarInf, levity2TyVarInf, levPolyAlphaTyVarSpec, levPolyBetaTyVarSpec, gammaTyVarSpec] [levPolyAlphaTy, levPolyBetaTy, (mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, gammaTy]))), mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, mkWeakPrimTy levPolyBetaTy]))+primOpInfo MkWeakNoFinalizerOp = mkGenPrimOp (fsLit "mkWeakNoFinalizer#") [levity1TyVarInf, levity2TyVarInf, levPolyAlphaTyVarSpec, levPolyBetaTyVarSpec] [levPolyAlphaTy, levPolyBetaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, mkWeakPrimTy levPolyBetaTy])) primOpInfo AddCFinalizerToWeakOp = mkGenPrimOp (fsLit "addCFinalizerToWeak#") [levity2TyVarInf, levPolyBetaTyVarSpec] [addrPrimTy, addrPrimTy, intPrimTy, addrPrimTy, mkWeakPrimTy levPolyBetaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, intPrimTy])) primOpInfo DeRefWeakOp = mkGenPrimOp (fsLit "deRefWeak#") [levity1TyVarInf, levPolyAlphaTyVarSpec] [mkWeakPrimTy levPolyAlphaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, intPrimTy, levPolyAlphaTy])) primOpInfo FinalizeWeakOp = mkGenPrimOp (fsLit "finalizeWeak#") [levity1TyVarInf, levPolyAlphaTyVarSpec, betaTyVarSpec] [mkWeakPrimTy levPolyAlphaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, intPrimTy, (mkVisFunTyMany (mkStatePrimTy realWorldTy) ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, betaTy])))]))@@ -620,13 +620,13 @@ primOpInfo CompactAdd = mkGenPrimOp (fsLit "compactAdd#") [alphaTyVarSpec] [compactPrimTy, alphaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, alphaTy])) primOpInfo CompactAddWithSharing = mkGenPrimOp (fsLit "compactAddWithSharing#") [alphaTyVarSpec] [compactPrimTy, alphaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, alphaTy])) primOpInfo CompactSize = mkGenPrimOp (fsLit "compactSize#") [] [compactPrimTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, wordPrimTy]))-primOpInfo ReallyUnsafePtrEqualityOp = mkGenPrimOp (fsLit "reallyUnsafePtrEquality#") [levity1TyVarInf, levPolyAlphaTyVarSpec, levity2TyVarInf, levPolyBetaTyVarSpec] [levPolyAlphaTy, levPolyBetaTy] (intPrimTy)+primOpInfo ReallyUnsafePtrEqualityOp = mkGenPrimOp (fsLit "reallyUnsafePtrEquality#") [levity1TyVarInf, levity2TyVarInf, levPolyAlphaTyVarSpec, levPolyBetaTyVarSpec] [levPolyAlphaTy, levPolyBetaTy] (intPrimTy) primOpInfo ParOp = mkGenPrimOp (fsLit "par#") [alphaTyVarSpec] [alphaTy] (intPrimTy) primOpInfo SparkOp = mkGenPrimOp (fsLit "spark#") [alphaTyVarSpec, deltaTyVarSpec] [alphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, alphaTy])) primOpInfo SeqOp = mkGenPrimOp (fsLit "seq#") [alphaTyVarSpec, deltaTyVarSpec] [alphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, alphaTy])) primOpInfo GetSparkOp = mkGenPrimOp (fsLit "getSpark#") [deltaTyVarSpec, alphaTyVarSpec] [mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, alphaTy])) primOpInfo NumSparks = mkGenPrimOp (fsLit "numSparks#") [deltaTyVarSpec] [mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))-primOpInfo KeepAliveOp = mkGenPrimOp (fsLit "keepAlive#") [levity1TyVarInf, levPolyAlphaTyVarSpec, runtimeRep2TyVarInf, openBetaTyVarSpec] [levPolyAlphaTy, mkStatePrimTy realWorldTy, (mkVisFunTyMany (mkStatePrimTy realWorldTy) (openBetaTy))] (openBetaTy)+primOpInfo KeepAliveOp = mkGenPrimOp (fsLit "keepAlive#") [levity1TyVarInf, runtimeRep2TyVarInf, levPolyAlphaTyVarSpec, openBetaTyVarSpec] [levPolyAlphaTy, mkStatePrimTy realWorldTy, (mkVisFunTyMany (mkStatePrimTy realWorldTy) (openBetaTy))] (openBetaTy) primOpInfo DataToTagOp = mkGenPrimOp (fsLit "dataToTag#") [alphaTyVarSpec] [alphaTy] (intPrimTy) primOpInfo TagToEnumOp = mkGenPrimOp (fsLit "tagToEnum#") [alphaTyVarSpec] [intPrimTy] (alphaTy) primOpInfo AddrToAnyOp = mkGenPrimOp (fsLit "addrToAny#") [alphaTyVarSpec] [addrPrimTy] ((mkTupleTy Unboxed [alphaTy]))
ghc-lib/stage0/compiler/build/primop-vector-tys.hs-incl view
@@ -3,178 +3,178 @@ int8X16PrimTy :: Type int8X16PrimTy = mkTyConTy int8X16PrimTyCon int8X16PrimTyCon :: TyCon-int8X16PrimTyCon = pcPrimTyCon0 int8X16PrimTyConName (VecRep 16 Int8ElemRep)+int8X16PrimTyCon = pcPrimTyCon0 int8X16PrimTyConName (TyConApp vecRepDataConTyCon [vec16DataConTy, int8ElemRepDataConTy]) int16X8PrimTyConName :: Name int16X8PrimTyConName = mkPrimTc (fsLit "Int16X8#") int16X8PrimTyConKey int16X8PrimTyCon int16X8PrimTy :: Type int16X8PrimTy = mkTyConTy int16X8PrimTyCon int16X8PrimTyCon :: TyCon-int16X8PrimTyCon = pcPrimTyCon0 int16X8PrimTyConName (VecRep 8 Int16ElemRep)+int16X8PrimTyCon = pcPrimTyCon0 int16X8PrimTyConName (TyConApp vecRepDataConTyCon [vec8DataConTy, int16ElemRepDataConTy]) int32X4PrimTyConName :: Name int32X4PrimTyConName = mkPrimTc (fsLit "Int32X4#") int32X4PrimTyConKey int32X4PrimTyCon int32X4PrimTy :: Type int32X4PrimTy = mkTyConTy int32X4PrimTyCon int32X4PrimTyCon :: TyCon-int32X4PrimTyCon = pcPrimTyCon0 int32X4PrimTyConName (VecRep 4 Int32ElemRep)+int32X4PrimTyCon = pcPrimTyCon0 int32X4PrimTyConName (TyConApp vecRepDataConTyCon [vec4DataConTy, int32ElemRepDataConTy]) int64X2PrimTyConName :: Name int64X2PrimTyConName = mkPrimTc (fsLit "Int64X2#") int64X2PrimTyConKey int64X2PrimTyCon int64X2PrimTy :: Type int64X2PrimTy = mkTyConTy int64X2PrimTyCon int64X2PrimTyCon :: TyCon-int64X2PrimTyCon = pcPrimTyCon0 int64X2PrimTyConName (VecRep 2 Int64ElemRep)+int64X2PrimTyCon = pcPrimTyCon0 int64X2PrimTyConName (TyConApp vecRepDataConTyCon [vec2DataConTy, int64ElemRepDataConTy]) int8X32PrimTyConName :: Name int8X32PrimTyConName = mkPrimTc (fsLit "Int8X32#") int8X32PrimTyConKey int8X32PrimTyCon int8X32PrimTy :: Type int8X32PrimTy = mkTyConTy int8X32PrimTyCon int8X32PrimTyCon :: TyCon-int8X32PrimTyCon = pcPrimTyCon0 int8X32PrimTyConName (VecRep 32 Int8ElemRep)+int8X32PrimTyCon = pcPrimTyCon0 int8X32PrimTyConName (TyConApp vecRepDataConTyCon [vec32DataConTy, int8ElemRepDataConTy]) int16X16PrimTyConName :: Name int16X16PrimTyConName = mkPrimTc (fsLit "Int16X16#") int16X16PrimTyConKey int16X16PrimTyCon int16X16PrimTy :: Type int16X16PrimTy = mkTyConTy int16X16PrimTyCon int16X16PrimTyCon :: TyCon-int16X16PrimTyCon = pcPrimTyCon0 int16X16PrimTyConName (VecRep 16 Int16ElemRep)+int16X16PrimTyCon = pcPrimTyCon0 int16X16PrimTyConName (TyConApp vecRepDataConTyCon [vec16DataConTy, int16ElemRepDataConTy]) int32X8PrimTyConName :: Name int32X8PrimTyConName = mkPrimTc (fsLit "Int32X8#") int32X8PrimTyConKey int32X8PrimTyCon int32X8PrimTy :: Type int32X8PrimTy = mkTyConTy int32X8PrimTyCon int32X8PrimTyCon :: TyCon-int32X8PrimTyCon = pcPrimTyCon0 int32X8PrimTyConName (VecRep 8 Int32ElemRep)+int32X8PrimTyCon = pcPrimTyCon0 int32X8PrimTyConName (TyConApp vecRepDataConTyCon [vec8DataConTy, int32ElemRepDataConTy]) int64X4PrimTyConName :: Name int64X4PrimTyConName = mkPrimTc (fsLit "Int64X4#") int64X4PrimTyConKey int64X4PrimTyCon int64X4PrimTy :: Type int64X4PrimTy = mkTyConTy int64X4PrimTyCon int64X4PrimTyCon :: TyCon-int64X4PrimTyCon = pcPrimTyCon0 int64X4PrimTyConName (VecRep 4 Int64ElemRep)+int64X4PrimTyCon = pcPrimTyCon0 int64X4PrimTyConName (TyConApp vecRepDataConTyCon [vec4DataConTy, int64ElemRepDataConTy]) int8X64PrimTyConName :: Name int8X64PrimTyConName = mkPrimTc (fsLit "Int8X64#") int8X64PrimTyConKey int8X64PrimTyCon int8X64PrimTy :: Type int8X64PrimTy = mkTyConTy int8X64PrimTyCon int8X64PrimTyCon :: TyCon-int8X64PrimTyCon = pcPrimTyCon0 int8X64PrimTyConName (VecRep 64 Int8ElemRep)+int8X64PrimTyCon = pcPrimTyCon0 int8X64PrimTyConName (TyConApp vecRepDataConTyCon [vec64DataConTy, int8ElemRepDataConTy]) int16X32PrimTyConName :: Name int16X32PrimTyConName = mkPrimTc (fsLit "Int16X32#") int16X32PrimTyConKey int16X32PrimTyCon int16X32PrimTy :: Type int16X32PrimTy = mkTyConTy int16X32PrimTyCon int16X32PrimTyCon :: TyCon-int16X32PrimTyCon = pcPrimTyCon0 int16X32PrimTyConName (VecRep 32 Int16ElemRep)+int16X32PrimTyCon = pcPrimTyCon0 int16X32PrimTyConName (TyConApp vecRepDataConTyCon [vec32DataConTy, int16ElemRepDataConTy]) int32X16PrimTyConName :: Name int32X16PrimTyConName = mkPrimTc (fsLit "Int32X16#") int32X16PrimTyConKey int32X16PrimTyCon int32X16PrimTy :: Type int32X16PrimTy = mkTyConTy int32X16PrimTyCon int32X16PrimTyCon :: TyCon-int32X16PrimTyCon = pcPrimTyCon0 int32X16PrimTyConName (VecRep 16 Int32ElemRep)+int32X16PrimTyCon = pcPrimTyCon0 int32X16PrimTyConName (TyConApp vecRepDataConTyCon [vec16DataConTy, int32ElemRepDataConTy]) int64X8PrimTyConName :: Name int64X8PrimTyConName = mkPrimTc (fsLit "Int64X8#") int64X8PrimTyConKey int64X8PrimTyCon int64X8PrimTy :: Type int64X8PrimTy = mkTyConTy int64X8PrimTyCon int64X8PrimTyCon :: TyCon-int64X8PrimTyCon = pcPrimTyCon0 int64X8PrimTyConName (VecRep 8 Int64ElemRep)+int64X8PrimTyCon = pcPrimTyCon0 int64X8PrimTyConName (TyConApp vecRepDataConTyCon [vec8DataConTy, int64ElemRepDataConTy]) word8X16PrimTyConName :: Name word8X16PrimTyConName = mkPrimTc (fsLit "Word8X16#") word8X16PrimTyConKey word8X16PrimTyCon word8X16PrimTy :: Type word8X16PrimTy = mkTyConTy word8X16PrimTyCon word8X16PrimTyCon :: TyCon-word8X16PrimTyCon = pcPrimTyCon0 word8X16PrimTyConName (VecRep 16 Word8ElemRep)+word8X16PrimTyCon = pcPrimTyCon0 word8X16PrimTyConName (TyConApp vecRepDataConTyCon [vec16DataConTy, word8ElemRepDataConTy]) word16X8PrimTyConName :: Name word16X8PrimTyConName = mkPrimTc (fsLit "Word16X8#") word16X8PrimTyConKey word16X8PrimTyCon word16X8PrimTy :: Type word16X8PrimTy = mkTyConTy word16X8PrimTyCon word16X8PrimTyCon :: TyCon-word16X8PrimTyCon = pcPrimTyCon0 word16X8PrimTyConName (VecRep 8 Word16ElemRep)+word16X8PrimTyCon = pcPrimTyCon0 word16X8PrimTyConName (TyConApp vecRepDataConTyCon [vec8DataConTy, word16ElemRepDataConTy]) word32X4PrimTyConName :: Name word32X4PrimTyConName = mkPrimTc (fsLit "Word32X4#") word32X4PrimTyConKey word32X4PrimTyCon word32X4PrimTy :: Type word32X4PrimTy = mkTyConTy word32X4PrimTyCon word32X4PrimTyCon :: TyCon-word32X4PrimTyCon = pcPrimTyCon0 word32X4PrimTyConName (VecRep 4 Word32ElemRep)+word32X4PrimTyCon = pcPrimTyCon0 word32X4PrimTyConName (TyConApp vecRepDataConTyCon [vec4DataConTy, word32ElemRepDataConTy]) word64X2PrimTyConName :: Name word64X2PrimTyConName = mkPrimTc (fsLit "Word64X2#") word64X2PrimTyConKey word64X2PrimTyCon word64X2PrimTy :: Type word64X2PrimTy = mkTyConTy word64X2PrimTyCon word64X2PrimTyCon :: TyCon-word64X2PrimTyCon = pcPrimTyCon0 word64X2PrimTyConName (VecRep 2 Word64ElemRep)+word64X2PrimTyCon = pcPrimTyCon0 word64X2PrimTyConName (TyConApp vecRepDataConTyCon [vec2DataConTy, word64ElemRepDataConTy]) word8X32PrimTyConName :: Name word8X32PrimTyConName = mkPrimTc (fsLit "Word8X32#") word8X32PrimTyConKey word8X32PrimTyCon word8X32PrimTy :: Type word8X32PrimTy = mkTyConTy word8X32PrimTyCon word8X32PrimTyCon :: TyCon-word8X32PrimTyCon = pcPrimTyCon0 word8X32PrimTyConName (VecRep 32 Word8ElemRep)+word8X32PrimTyCon = pcPrimTyCon0 word8X32PrimTyConName (TyConApp vecRepDataConTyCon [vec32DataConTy, word8ElemRepDataConTy]) word16X16PrimTyConName :: Name word16X16PrimTyConName = mkPrimTc (fsLit "Word16X16#") word16X16PrimTyConKey word16X16PrimTyCon word16X16PrimTy :: Type word16X16PrimTy = mkTyConTy word16X16PrimTyCon word16X16PrimTyCon :: TyCon-word16X16PrimTyCon = pcPrimTyCon0 word16X16PrimTyConName (VecRep 16 Word16ElemRep)+word16X16PrimTyCon = pcPrimTyCon0 word16X16PrimTyConName (TyConApp vecRepDataConTyCon [vec16DataConTy, word16ElemRepDataConTy]) word32X8PrimTyConName :: Name word32X8PrimTyConName = mkPrimTc (fsLit "Word32X8#") word32X8PrimTyConKey word32X8PrimTyCon word32X8PrimTy :: Type word32X8PrimTy = mkTyConTy word32X8PrimTyCon word32X8PrimTyCon :: TyCon-word32X8PrimTyCon = pcPrimTyCon0 word32X8PrimTyConName (VecRep 8 Word32ElemRep)+word32X8PrimTyCon = pcPrimTyCon0 word32X8PrimTyConName (TyConApp vecRepDataConTyCon [vec8DataConTy, word32ElemRepDataConTy]) word64X4PrimTyConName :: Name word64X4PrimTyConName = mkPrimTc (fsLit "Word64X4#") word64X4PrimTyConKey word64X4PrimTyCon word64X4PrimTy :: Type word64X4PrimTy = mkTyConTy word64X4PrimTyCon word64X4PrimTyCon :: TyCon-word64X4PrimTyCon = pcPrimTyCon0 word64X4PrimTyConName (VecRep 4 Word64ElemRep)+word64X4PrimTyCon = pcPrimTyCon0 word64X4PrimTyConName (TyConApp vecRepDataConTyCon [vec4DataConTy, word64ElemRepDataConTy]) word8X64PrimTyConName :: Name word8X64PrimTyConName = mkPrimTc (fsLit "Word8X64#") word8X64PrimTyConKey word8X64PrimTyCon word8X64PrimTy :: Type word8X64PrimTy = mkTyConTy word8X64PrimTyCon word8X64PrimTyCon :: TyCon-word8X64PrimTyCon = pcPrimTyCon0 word8X64PrimTyConName (VecRep 64 Word8ElemRep)+word8X64PrimTyCon = pcPrimTyCon0 word8X64PrimTyConName (TyConApp vecRepDataConTyCon [vec64DataConTy, word8ElemRepDataConTy]) word16X32PrimTyConName :: Name word16X32PrimTyConName = mkPrimTc (fsLit "Word16X32#") word16X32PrimTyConKey word16X32PrimTyCon word16X32PrimTy :: Type word16X32PrimTy = mkTyConTy word16X32PrimTyCon word16X32PrimTyCon :: TyCon-word16X32PrimTyCon = pcPrimTyCon0 word16X32PrimTyConName (VecRep 32 Word16ElemRep)+word16X32PrimTyCon = pcPrimTyCon0 word16X32PrimTyConName (TyConApp vecRepDataConTyCon [vec32DataConTy, word16ElemRepDataConTy]) word32X16PrimTyConName :: Name word32X16PrimTyConName = mkPrimTc (fsLit "Word32X16#") word32X16PrimTyConKey word32X16PrimTyCon word32X16PrimTy :: Type word32X16PrimTy = mkTyConTy word32X16PrimTyCon word32X16PrimTyCon :: TyCon-word32X16PrimTyCon = pcPrimTyCon0 word32X16PrimTyConName (VecRep 16 Word32ElemRep)+word32X16PrimTyCon = pcPrimTyCon0 word32X16PrimTyConName (TyConApp vecRepDataConTyCon [vec16DataConTy, word32ElemRepDataConTy]) word64X8PrimTyConName :: Name word64X8PrimTyConName = mkPrimTc (fsLit "Word64X8#") word64X8PrimTyConKey word64X8PrimTyCon word64X8PrimTy :: Type word64X8PrimTy = mkTyConTy word64X8PrimTyCon word64X8PrimTyCon :: TyCon-word64X8PrimTyCon = pcPrimTyCon0 word64X8PrimTyConName (VecRep 8 Word64ElemRep)+word64X8PrimTyCon = pcPrimTyCon0 word64X8PrimTyConName (TyConApp vecRepDataConTyCon [vec8DataConTy, word64ElemRepDataConTy]) floatX4PrimTyConName :: Name floatX4PrimTyConName = mkPrimTc (fsLit "FloatX4#") floatX4PrimTyConKey floatX4PrimTyCon floatX4PrimTy :: Type floatX4PrimTy = mkTyConTy floatX4PrimTyCon floatX4PrimTyCon :: TyCon-floatX4PrimTyCon = pcPrimTyCon0 floatX4PrimTyConName (VecRep 4 FloatElemRep)+floatX4PrimTyCon = pcPrimTyCon0 floatX4PrimTyConName (TyConApp vecRepDataConTyCon [vec4DataConTy, floatElemRepDataConTy]) doubleX2PrimTyConName :: Name doubleX2PrimTyConName = mkPrimTc (fsLit "DoubleX2#") doubleX2PrimTyConKey doubleX2PrimTyCon doubleX2PrimTy :: Type doubleX2PrimTy = mkTyConTy doubleX2PrimTyCon doubleX2PrimTyCon :: TyCon-doubleX2PrimTyCon = pcPrimTyCon0 doubleX2PrimTyConName (VecRep 2 DoubleElemRep)+doubleX2PrimTyCon = pcPrimTyCon0 doubleX2PrimTyConName (TyConApp vecRepDataConTyCon [vec2DataConTy, doubleElemRepDataConTy]) floatX8PrimTyConName :: Name floatX8PrimTyConName = mkPrimTc (fsLit "FloatX8#") floatX8PrimTyConKey floatX8PrimTyCon floatX8PrimTy :: Type floatX8PrimTy = mkTyConTy floatX8PrimTyCon floatX8PrimTyCon :: TyCon-floatX8PrimTyCon = pcPrimTyCon0 floatX8PrimTyConName (VecRep 8 FloatElemRep)+floatX8PrimTyCon = pcPrimTyCon0 floatX8PrimTyConName (TyConApp vecRepDataConTyCon [vec8DataConTy, floatElemRepDataConTy]) doubleX4PrimTyConName :: Name doubleX4PrimTyConName = mkPrimTc (fsLit "DoubleX4#") doubleX4PrimTyConKey doubleX4PrimTyCon doubleX4PrimTy :: Type doubleX4PrimTy = mkTyConTy doubleX4PrimTyCon doubleX4PrimTyCon :: TyCon-doubleX4PrimTyCon = pcPrimTyCon0 doubleX4PrimTyConName (VecRep 4 DoubleElemRep)+doubleX4PrimTyCon = pcPrimTyCon0 doubleX4PrimTyConName (TyConApp vecRepDataConTyCon [vec4DataConTy, doubleElemRepDataConTy]) floatX16PrimTyConName :: Name floatX16PrimTyConName = mkPrimTc (fsLit "FloatX16#") floatX16PrimTyConKey floatX16PrimTyCon floatX16PrimTy :: Type floatX16PrimTy = mkTyConTy floatX16PrimTyCon floatX16PrimTyCon :: TyCon-floatX16PrimTyCon = pcPrimTyCon0 floatX16PrimTyConName (VecRep 16 FloatElemRep)+floatX16PrimTyCon = pcPrimTyCon0 floatX16PrimTyConName (TyConApp vecRepDataConTyCon [vec16DataConTy, floatElemRepDataConTy]) doubleX8PrimTyConName :: Name doubleX8PrimTyConName = mkPrimTc (fsLit "DoubleX8#") doubleX8PrimTyConKey doubleX8PrimTyCon doubleX8PrimTy :: Type doubleX8PrimTy = mkTyConTy doubleX8PrimTyCon doubleX8PrimTyCon :: TyCon-doubleX8PrimTyCon = pcPrimTyCon0 doubleX8PrimTyConName (VecRep 8 DoubleElemRep)+doubleX8PrimTyCon = pcPrimTyCon0 doubleX8PrimTyConName (TyConApp vecRepDataConTyCon [vec8DataConTy, doubleElemRepDataConTy])
ghc-lib/stage0/rts/build/include/GhclibDerivedConstants.h view
@@ -1,6 +1,6 @@ /* This file is created automatically. Do not edit by hand.*/ -#define HS_CONSTANTS "291,1,2,4096,252,9,0,8,16,24,32,40,48,56,64,72,80,84,88,92,96,100,104,112,120,128,136,144,152,168,184,200,216,232,248,280,312,344,376,408,440,504,568,632,696,760,824,832,840,848,856,864,872,888,904,-24,-16,-8,24,0,8,48,46,96,72,8,48,8,8,16,8,48,8,16,8,0,56,40,8,16,0,8,8,0,8,0,96,112,16,8,16,0,4,4,24,20,4,15,7,1,-16,255,0,255,7,10,6,6,1,6,6,6,6,6,0,16384,21,1024,8,4,8,8,6,3,30,1152921503533105152,0,1152921504606846976,1"+#define HS_CONSTANTS "291,1,2,4096,252,9,0,8,16,24,32,40,48,56,64,72,80,84,88,92,96,100,104,112,120,128,136,144,152,168,184,200,216,232,248,280,312,344,376,408,440,504,568,632,696,760,824,832,840,848,856,864,872,888,904,-24,-16,-8,24,0,8,48,46,96,72,8,48,8,8,16,8,56,8,16,8,0,64,48,8,16,0,8,8,0,8,0,96,112,16,8,16,0,4,4,24,20,4,15,7,1,-16,255,0,255,7,10,6,6,1,6,6,6,6,6,0,16384,21,1024,8,4,8,8,6,3,30,1152921503533105152,0,1152921504606846976,1" #define CONTROL_GROUP_CONST_291 291 #define STD_HDR_SIZE 1 #define PROF_HDR_SIZE 2@@ -149,7 +149,7 @@ #define SIZEOF_StgSMPThunkHeader 8 #define OFFSET_StgClosure_payload 0 #define StgClosure_payload(__ptr__,__ix__) W_[__ptr__+SIZEOF_StgHeader+OFFSET_StgClosure_payload + WDS(__ix__)]-#define OFFSET_StgEntCounter_allocs 48+#define OFFSET_StgEntCounter_allocs 56 #define REP_StgEntCounter_allocs b64 #define StgEntCounter_allocs(__ptr__) REP_StgEntCounter_allocs[__ptr__+OFFSET_StgEntCounter_allocs] #define OFFSET_StgEntCounter_allocd 16@@ -158,10 +158,10 @@ #define OFFSET_StgEntCounter_registeredp 0 #define REP_StgEntCounter_registeredp b64 #define StgEntCounter_registeredp(__ptr__) REP_StgEntCounter_registeredp[__ptr__+OFFSET_StgEntCounter_registeredp]-#define OFFSET_StgEntCounter_link 56+#define OFFSET_StgEntCounter_link 64 #define REP_StgEntCounter_link b64 #define StgEntCounter_link(__ptr__) REP_StgEntCounter_link[__ptr__+OFFSET_StgEntCounter_link]-#define OFFSET_StgEntCounter_entry_count 40+#define OFFSET_StgEntCounter_entry_count 48 #define REP_StgEntCounter_entry_count b64 #define StgEntCounter_entry_count(__ptr__) REP_StgEntCounter_entry_count[__ptr__+OFFSET_StgEntCounter_entry_count] #define SIZEOF_StgUpdateFrame_NoHdr 8
ghc-lib/stage0/rts/build/include/ghcautoconf.h view
@@ -626,7 +626,7 @@ /* #undef pid_t */ /* The maximum supported LLVM version number */-#define sUPPORTED_LLVM_VERSION_MAX (13)+#define sUPPORTED_LLVM_VERSION_MAX (14) /* The minimum supported LLVM version number */ #define sUPPORTED_LLVM_VERSION_MIN (9)