ghc-lib 0.20201201 → 0.20210101
raw patch · 120 files changed
+13306/−12360 lines, 120 filesdep ~ghc-lib-parserPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: ghc-lib-parser
API changes (from Hackage documentation)
- GHC: Opt_FlatCache :: GeneralFlag
- GHC: [unitDatabases] :: DynFlags -> Maybe [UnitDatabase UnitId]
- GHC: [unitState] :: DynFlags -> UnitState
- GHC.Core.Opt.WorkWrap.Utils: DataConAppContext :: !DataCon -> ![Type] -> ![(Scaled Type, StrictnessMark)] -> !Coercion -> DataConAppContext
- GHC.Core.Opt.WorkWrap.Utils: [dcac_arg_tys] :: DataConAppContext -> ![(Scaled Type, StrictnessMark)]
- GHC.Core.Opt.WorkWrap.Utils: [dcac_co] :: DataConAppContext -> !Coercion
- GHC.Core.Opt.WorkWrap.Utils: [dcac_dc] :: DataConAppContext -> !DataCon
- GHC.Core.Opt.WorkWrap.Utils: [dcac_tys] :: DataConAppContext -> ![Type]
- GHC.Core.Opt.WorkWrap.Utils: data DataConAppContext
- GHC.Core.Opt.WorkWrap.Utils: deepSplitProductType_maybe :: FamInstEnvs -> Type -> Maybe DataConAppContext
- GHC.Driver.Make: implicitRequirements :: HscEnv -> [(Maybe FastString, Located ModuleName)] -> IO [(Maybe FastString, Located ModuleName)]
- GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie arg, GHC.Iface.Ext.Ast.ToHie rec) => GHC.Iface.Ext.Ast.ToHie (GHC.Hs.Type.HsConDetails arg rec)
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.Context a) => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.PatSynFieldContext (GHC.Hs.Binds.RecordPatSynField a))
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.IEContext (GHC.Types.SrcLoc.Located (GHC.Types.FieldLabel.FieldLbl GHC.Types.Name.Name)))
- GHC.Linker.MacOS: getUnitFrameworkPath :: SDocContext -> UnitState -> HomeUnit -> [UnitId] -> IO [String]
- GHC.Linker.MacOS: getUnitFrameworks :: SDocContext -> UnitState -> HomeUnit -> [UnitId] -> IO [String]
- GHC.Linker.Unit: collectLibraryPaths :: Ways -> [UnitInfo] -> [FilePath]
- GHC.Linker.Unit: getUnitLibraryPath :: SDocContext -> UnitState -> HomeUnit -> Ways -> [UnitId] -> IO [String]
- GHC.Linker.Unit: packageHsLibs :: DynFlags -> UnitInfo -> [String]
- GHC.Plugins: NoBlockSubst :: BlockSubstFlag
- GHC.Plugins: YesBlockSubst :: BlockSubstFlag
- GHC.Plugins: [ch_blocker] :: CoercionHole -> BlockSubstFlag
- GHC.Plugins: badCoercionHole :: Type -> Bool
- GHC.Plugins: badCoercionHoleCo :: Coercion -> Bool
- GHC.Plugins: data BlockSubstFlag
- GHC.Rename.Env: FoundFL :: FieldLabel -> ChildLookupResult
- GHC.Rename.Env: FoundName :: Parent -> Name -> ChildLookupResult
- GHC.Rename.HsType: rnImplicitBndrs :: Maybe assoc -> FreeKiTyVars -> ([Name] -> RnM (a, FreeVars)) -> RnM (a, FreeVars)
- GHC.Runtime.Eval: availsToGlobalRdrEnv :: ModuleName -> [AvailInfo] -> GlobalRdrEnv
- GHC.Runtime.Eval: hasImport :: ParserOpts -> String -> Bool
- GHC.Runtime.Eval: isDecl :: ParserOpts -> String -> Bool
- GHC.Runtime.Eval: isImport :: ParserOpts -> String -> Bool
- GHC.Runtime.Eval: isStmt :: ParserOpts -> String -> Bool
- GHC.Tc.Solver.Canonical: maybeSym :: SwapFlag -> TcCoercion -> TcCoercion
- GHC.Tc.Solver.Flatten: FM_FlattenAll :: FlattenMode
- GHC.Tc.Solver.Flatten: FM_SubstOnly :: FlattenMode
- GHC.Tc.Solver.Flatten: data FlattenMode
- GHC.Tc.Solver.Flatten: flatten :: FlattenMode -> CtEvidence -> TcType -> TcS (Xi, TcCoercion)
- GHC.Tc.Solver.Flatten: flattenArgsNom :: CtEvidence -> TyCon -> [TcType] -> TcS ([Xi], [TcCoercion], TcCoercionN)
- GHC.Tc.Solver.Flatten: flattenKind :: CtLoc -> CtFlavour -> TcType -> TcS (Xi, TcCoercionN)
- GHC.Tc.Solver.Flatten: flattenType :: CtLoc -> TcType -> TcS TcType
- GHC.Tc.Solver.Flatten: instance GHC.Base.Applicative GHC.Tc.Solver.Flatten.FlatM
- GHC.Tc.Solver.Flatten: instance GHC.Base.Functor GHC.Tc.Solver.Flatten.FlatM
- GHC.Tc.Solver.Flatten: instance GHC.Base.Monad GHC.Tc.Solver.Flatten.FlatM
- GHC.Tc.Solver.Flatten: instance GHC.Utils.Outputable.Outputable GHC.Tc.Solver.Flatten.FlattenMode
- GHC.Tc.Solver.Flatten: rewriteTyVar :: TcTyVar -> TcS TcType
- GHC.Tc.Solver.Flatten: unflattenWanteds :: Cts -> Cts -> TcS Cts
- GHC.Tc.Solver.Monad: [inert_count] :: InertCans -> Int
- GHC.Tc.Solver.Monad: [inert_flat_cache] :: InertSet -> ExactFunEqMap (TcCoercion, TcType, CtFlavour)
- GHC.Tc.Solver.Monad: [inert_fsks] :: InertSet -> [(TcTyVar, TcType)]
- GHC.Tc.Solver.Monad: [wl_funeqs] :: WorkList -> [Ct]
- GHC.Tc.Solver.Monad: demoteUnfilledFmv :: TcTyVar -> TcS ()
- GHC.Tc.Solver.Monad: dischargeFunEq :: CtEvidence -> TcTyVar -> TcCoercion -> TcType -> TcS ()
- GHC.Tc.Solver.Monad: extendFlatCache :: TyCon -> [Type] -> (TcCoercion, TcType, CtFlavour) -> TcS ()
- GHC.Tc.Solver.Monad: extendWorkListFunEq :: Ct -> WorkList -> WorkList
- GHC.Tc.Solver.Monad: getNoGivenEqs :: TcLevel -> [TcTyVar] -> TcS (Bool, Cts)
- GHC.Tc.Solver.Monad: isInInertEqs :: DTyVarEnv EqualCtList -> TcTyVar -> TcType -> Bool
- GHC.Tc.Solver.Monad: lookupFlatCache :: TyCon -> [Type] -> TcS (Maybe (TcCoercion, TcType, CtFlavour))
- GHC.Tc.Solver.Monad: lookupInertTyVar :: InertEqs -> TcTyVar -> Maybe TcType
- GHC.Tc.Solver.Monad: newFlattenSkolem :: CtFlavour -> CtLoc -> TyCon -> [TcType] -> TcS (CtEvidence, Coercion, TcTyVar)
- GHC.Tc.Solver.Monad: type EqualCtList = [Ct]
- GHC.Tc.Solver.Monad: unflattenFmv :: TcTyVar -> TcType -> TcS ()
- GHC.Tc.Solver.Monad: updInertFunEqs :: (FunEqMap Ct -> FunEqMap Ct) -> TcS ()
- GHC.Tc.Solver.Monad: workListWantedCount :: WorkList -> Int
- GHC.Tc.Utils.TcMType: newFmvTyVar :: TcType -> TcM TcTyVar
- GHC.Tc.Utils.TcMType: newFskTyVar :: TcType -> TcM TcTyVar
- GHC.Tc.Utils.TcMType: promoteTyVar :: TcTyVar -> TcM Bool
- GHC.Tc.Utils.Unify: MTVU_Bad :: MetaTyVarUpdateResult a
- GHC.Tc.Utils.Unify: MTVU_HoleBlocker :: MetaTyVarUpdateResult a
- GHC.Tc.Utils.Unify: MTVU_OK :: a -> MetaTyVarUpdateResult a
- GHC.Tc.Utils.Unify: MTVU_Occurs :: MetaTyVarUpdateResult a
- GHC.Tc.Utils.Unify: data MetaTyVarUpdateResult a
- GHC.Tc.Utils.Unify: instance GHC.Base.Applicative GHC.Tc.Utils.Unify.MetaTyVarUpdateResult
- GHC.Tc.Utils.Unify: instance GHC.Base.Functor GHC.Tc.Utils.Unify.MetaTyVarUpdateResult
- GHC.Tc.Utils.Unify: instance GHC.Base.Monad GHC.Tc.Utils.Unify.MetaTyVarUpdateResult
- GHC.Tc.Utils.Unify: instance GHC.Utils.Outputable.Outputable a => GHC.Utils.Outputable.Outputable (GHC.Tc.Utils.Unify.MetaTyVarUpdateResult a)
- GHC.Tc.Utils.Unify: metaTyVarUpdateOK :: DynFlags -> TcTyVar -> TcType -> MetaTyVarUpdateResult TcType
- GHC.Unit.Finder: cannotFindInterface :: DynFlags -> ModuleName -> InstalledFindResult -> SDoc
- GHC.Unit.Finder: cannotFindModule :: DynFlags -> ModuleName -> FindResult -> SDoc
- GHCi.InfoTable: instance GHC.Show.Show GHCi.InfoTable.Arch
+ GHC: Opt_FamAppCache :: GeneralFlag
+ GHC.Cmm.LRegSet: deleteFromLRegSet :: LRegSet -> LocalReg -> LRegSet
+ GHC.Cmm.LRegSet: elemLRegSet :: LocalReg -> LRegSet -> Bool
+ GHC.Cmm.LRegSet: elemsLRegSet :: IntSet -> [Int]
+ GHC.Cmm.LRegSet: emptyLRegSet :: LRegSet
+ GHC.Cmm.LRegSet: insertLRegSet :: LocalReg -> LRegSet -> LRegSet
+ GHC.Cmm.LRegSet: nullLRegSet :: LRegSet -> Bool
+ GHC.Cmm.LRegSet: plusLRegSet :: IntSet -> IntSet -> IntSet
+ GHC.Cmm.LRegSet: sizeLRegSet :: IntSet -> Int
+ GHC.Cmm.LRegSet: type LRegKey = Int
+ GHC.Cmm.LRegSet: type LRegSet = IntSet
+ GHC.Cmm.Liveness: cmmLocalLivenessL :: Platform -> CmmGraph -> BlockEntryLivenessL
+ GHC.Cmm.Liveness: gen_killL :: (DefinerOfRegs LocalReg n, UserOfRegs LocalReg n) => Platform -> n -> LRegSet -> LRegSet
+ GHC.Cmm.Liveness: liveLatticeL :: DataflowLattice LRegSet
+ GHC.Core.Map.Expr: (>.>) :: (a -> b) -> (b -> c) -> a -> c
+ GHC.Core.Map.Expr: (|>) :: a -> (a -> b) -> b
+ GHC.Core.Map.Expr: (|>>) :: TrieMap m2 => (XT (m2 a) -> m1 (m2 a) -> m1 (m2 a)) -> (m2 a -> m2 a) -> m1 (m2 a) -> m1 (m2 a)
+ GHC.Core.Map.Expr: alterTM :: TrieMap m => Key m -> XT b -> m b -> m b
+ GHC.Core.Map.Expr: class TrieMap (m :: Type -> Type) where {
+ GHC.Core.Map.Expr: data CoreMap a
+ GHC.Core.Map.Expr: deleteTM :: TrieMap m => Key m -> m a -> m a
+ GHC.Core.Map.Expr: emptyCoreMap :: CoreMap a
+ GHC.Core.Map.Expr: emptyTM :: TrieMap m => m a
+ GHC.Core.Map.Expr: extendCoreMap :: CoreMap a -> CoreExpr -> a -> CoreMap a
+ GHC.Core.Map.Expr: filterTM :: TrieMap m => (a -> Bool) -> m a -> m a
+ GHC.Core.Map.Expr: foldCoreMap :: (a -> b -> b) -> b -> CoreMap a -> b
+ GHC.Core.Map.Expr: foldTM :: TrieMap m => (a -> b -> b) -> m a -> b -> b
+ GHC.Core.Map.Expr: insertTM :: TrieMap m => Key m -> a -> m a -> m a
+ GHC.Core.Map.Expr: instance GHC.Classes.Eq (GHC.Core.Map.Type.DeBruijn GHC.Core.CoreAlt)
+ GHC.Core.Map.Expr: instance GHC.Classes.Eq (GHC.Core.Map.Type.DeBruijn GHC.Core.CoreExpr)
+ GHC.Core.Map.Expr: instance GHC.Data.TrieMap.TrieMap GHC.Core.Map.Expr.AltMap
+ GHC.Core.Map.Expr: instance GHC.Data.TrieMap.TrieMap GHC.Core.Map.Expr.CoreMap
+ GHC.Core.Map.Expr: instance GHC.Data.TrieMap.TrieMap GHC.Core.Map.Expr.CoreMapX
+ GHC.Core.Map.Expr: instance GHC.Utils.Outputable.Outputable a => GHC.Utils.Outputable.Outputable (GHC.Core.Map.Expr.CoreMap a)
+ GHC.Core.Map.Expr: lkDFreeVar :: Var -> DVarEnv a -> Maybe a
+ GHC.Core.Map.Expr: lkDNamed :: NamedThing n => n -> DNameEnv a -> Maybe a
+ GHC.Core.Map.Expr: lookupCoreMap :: CoreMap a -> CoreExpr -> Maybe a
+ GHC.Core.Map.Expr: lookupTM :: TrieMap m => Key m -> m b -> Maybe b
+ GHC.Core.Map.Expr: mapTM :: TrieMap m => (a -> b) -> m a -> m b
+ GHC.Core.Map.Expr: type family Key (m :: Type -> Type);
+ GHC.Core.Map.Expr: xtDFreeVar :: Var -> XT a -> DVarEnv a -> DVarEnv a
+ GHC.Core.Map.Expr: xtDNamed :: NamedThing n => n -> XT a -> DNameEnv a -> DNameEnv a
+ GHC.Core.Map.Expr: }
+ GHC.Core.Opt.WorkWrap.Utils: DataConPatContext :: !DataCon -> ![Type] -> !Coercion -> DataConPatContext
+ GHC.Core.Opt.WorkWrap.Utils: [dcpc_co] :: DataConPatContext -> !Coercion
+ GHC.Core.Opt.WorkWrap.Utils: [dcpc_dc] :: DataConPatContext -> !DataCon
+ GHC.Core.Opt.WorkWrap.Utils: [dcpc_tc_args] :: DataConPatContext -> ![Type]
+ GHC.Core.Opt.WorkWrap.Utils: data DataConPatContext
+ GHC.Core.Opt.WorkWrap.Utils: splitArgType_maybe :: FamInstEnvs -> Type -> Maybe DataConPatContext
+ GHC.Driver.Make: ModNodeMap :: Map ModNodeKey a -> ModNodeMap a
+ GHC.Driver.Make: [unModNodeMap] :: ModNodeMap a -> Map ModNodeKey a
+ GHC.Driver.Make: emptyModNodeMap :: ModNodeMap a
+ GHC.Driver.Make: implicitRequirementsShallow :: HscEnv -> [(Maybe FastString, Located ModuleName)] -> IO ([ModuleName], [InstantiatedUnit])
+ GHC.Driver.Make: instance Data.Foldable.Foldable GHC.Driver.Make.ModNodeMap
+ GHC.Driver.Make: instance Data.Foldable.Foldable GHC.Driver.Make.NodeMap
+ GHC.Driver.Make: instance Data.Traversable.Traversable GHC.Driver.Make.ModNodeMap
+ GHC.Driver.Make: instance Data.Traversable.Traversable GHC.Driver.Make.NodeMap
+ GHC.Driver.Make: instance GHC.Base.Functor GHC.Driver.Make.ModNodeMap
+ GHC.Driver.Make: instance GHC.Base.Functor GHC.Driver.Make.NodeMap
+ GHC.Driver.Make: instance GHC.Classes.Eq GHC.Driver.Make.BuildModule
+ GHC.Driver.Make: instance GHC.Classes.Eq GHC.Driver.Make.NodeKey
+ GHC.Driver.Make: instance GHC.Classes.Ord GHC.Driver.Make.BuildModule
+ GHC.Driver.Make: instance GHC.Classes.Ord GHC.Driver.Make.NodeKey
+ GHC.Driver.Make: instantiationNodes :: UnitState -> [ModuleGraphNode]
+ GHC.Driver.Make: modNodeMapElems :: ModNodeMap a -> [a]
+ GHC.Driver.Make: modNodeMapInsert :: ModNodeKey -> a -> ModNodeMap a -> ModNodeMap a
+ GHC.Driver.Make: modNodeMapLookup :: ModNodeKey -> ModNodeMap a -> Maybe a
+ GHC.Driver.Make: newtype ModNodeMap a
+ GHC.HsToCore.Binds: dsEvTerm :: EvTerm -> DsM CoreExpr
+ GHC.HsToCore.Types: [ds_gbl_rdr_env] :: DsGblEnv -> GlobalRdrEnv
+ GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie tyarg, GHC.Iface.Ext.Ast.ToHie arg, GHC.Iface.Ext.Ast.ToHie rec) => GHC.Iface.Ext.Ast.ToHie (GHC.Hs.Type.HsConDetails tyarg arg rec)
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.Context (GHC.Hs.Type.FieldOcc (GHC.Hs.Extension.GhcPass p)))
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.PatSynFieldContext (GHC.Hs.Binds.RecordPatSynField (GHC.Hs.Extension.GhcPass p)))
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.IEContext (GHC.Types.SrcLoc.Located GHC.Types.FieldLabel.FieldLabel))
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.ToHie Data.Void.Void
+ GHC.Iface.Load: cannotFindModule :: HscEnv -> ModuleName -> FindResult -> SDoc
+ GHC.Parser.Utils: hasImport :: ParserOpts -> String -> Bool
+ GHC.Parser.Utils: isDecl :: ParserOpts -> String -> Bool
+ GHC.Parser.Utils: isImport :: ParserOpts -> String -> Bool
+ GHC.Parser.Utils: isStmt :: ParserOpts -> String -> Bool
+ GHC.Plugins: anyFreeVarsOfCo :: (TyCoVar -> Bool) -> Coercion -> Bool
+ GHC.Plugins: anyFreeVarsOfType :: (TyCoVar -> Bool) -> Type -> Bool
+ GHC.Plugins: anyFreeVarsOfTypes :: (TyCoVar -> Bool) -> [Type] -> Bool
+ GHC.Plugins: coercionHolesOfCo :: Coercion -> UniqSet CoercionHole
+ GHC.Plugins: coercionHolesOfType :: Type -> UniqSet CoercionHole
+ GHC.Plugins: hasCoercionHoleCo :: Coercion -> Bool
+ GHC.Plugins: hasCoercionHoleTy :: Type -> Bool
+ GHC.Plugins: isReflMCo :: MCoercion -> Bool
+ GHC.Plugins: mkCastTyMCo :: Type -> MCoercion -> Type
+ GHC.Plugins: mkCoherenceRightMCo :: Role -> Type -> MCoercionN -> Coercion -> Coercion
+ GHC.Plugins: mkFunTy :: AnonArgFlag -> Mult -> Type -> Type -> Type
+ GHC.Plugins: mkGReflLeftMCo :: Role -> Type -> MCoercionN -> Coercion
+ GHC.Plugins: mkGReflRightMCo :: Role -> Type -> MCoercionN -> Coercion
+ GHC.Plugins: mkSymMCo :: MCoercion -> MCoercion
+ GHC.Plugins: substTyCoBndr :: TCvSubst -> TyCoBinder -> (TCvSubst, TyCoBinder)
+ GHC.Plugins: type HoleSet = UniqSet CoercionHole
+ GHC.Plugins: type MCoercionN = MCoercion
+ GHC.Rename.Env: FoundChild :: Parent -> GreName -> ChildLookupResult
+ GHC.Rename.HsType: lookupField :: FastStringEnv FieldLabel -> FieldOcc GhcPs -> FieldOcc GhcRn
+ GHC.Rename.HsType: rnHsPatSigTypeBindingVars :: HsDocContext -> HsPatSigType GhcPs -> (HsPatSigType GhcRn -> RnM (r, FreeVars)) -> RnM (r, FreeVars)
+ GHC.Rename.HsType: rnImplicitTvOccs :: Maybe assoc -> FreeKiTyVars -> ([Name] -> RnM (a, FreeVars)) -> RnM (a, FreeVars)
+ GHC.Rename.Pat: liftCpsWithCont :: (forall r. (b -> RnM (r, FreeVars)) -> RnM (r, FreeVars)) -> CpsRn b
+ GHC.Rename.Utils: HsTypePatCtx :: HsDocContext
+ GHC.Tc.Gen.HsType: HM_FamPat :: HoleMode
+ GHC.Tc.Gen.HsType: HM_Sig :: HoleMode
+ GHC.Tc.Gen.HsType: HM_TyAppPat :: HoleMode
+ GHC.Tc.Gen.HsType: HM_VTA :: HoleMode
+ GHC.Tc.Gen.HsType: data HoleMode
+ GHC.Tc.Solver.Canonical: NoUnify :: UnifyTestResult
+ GHC.Tc.Solver.Canonical: UnifyOuterLevel :: [TcTyVar] -> TcLevel -> UnifyTestResult
+ GHC.Tc.Solver.Canonical: UnifySameLevel :: UnifyTestResult
+ GHC.Tc.Solver.Canonical: andWhenContinue :: TcS (StopOrContinue a) -> (a -> TcS (StopOrContinue b)) -> TcS (StopOrContinue b)
+ GHC.Tc.Solver.Canonical: data UnifyTestResult
+ GHC.Tc.Solver.Canonical: infixr 0 `andWhenContinue`
+ GHC.Tc.Solver.Canonical: instance GHC.Utils.Outputable.Outputable GHC.Tc.Solver.Canonical.CanEqOK
+ GHC.Tc.Solver.Canonical: instance GHC.Utils.Outputable.Outputable GHC.Tc.Solver.Canonical.UnifyTestResult
+ GHC.Tc.Solver.Canonical: unifyTest :: CtEvidence -> TcTyVar -> TcType -> TcS UnifyTestResult
+ GHC.Tc.Solver.Monad: EqualCtList :: NonEmpty Ct -> EqualCtList
+ GHC.Tc.Solver.Monad: [inert_cycle_breakers] :: InertSet -> [(TcTyVar, TcType)]
+ GHC.Tc.Solver.Monad: [inert_famapp_cache] :: InertSet -> FunEqMap (TcCoercion, TcType)
+ GHC.Tc.Solver.Monad: [inert_given_eq_lvl] :: InertCans -> TcLevel
+ GHC.Tc.Solver.Monad: [inert_given_eqs] :: InertCans -> Bool
+ GHC.Tc.Solver.Monad: breakTyVarCycle :: CtLoc -> TcType -> TcS TcType
+ GHC.Tc.Solver.Monad: extendFamAppCache :: TyCon -> [Type] -> (TcCoercion, TcType) -> TcS ()
+ GHC.Tc.Solver.Monad: findEq :: InertCans -> CanEqLHS -> [Ct]
+ GHC.Tc.Solver.Monad: getHasGivenEqs :: TcLevel -> TcS (HasGivenEqs, Cts)
+ GHC.Tc.Solver.Monad: getInnermostGivenEqLevel :: TcS TcLevel
+ GHC.Tc.Solver.Monad: instance GHC.Utils.Outputable.Outputable GHC.Tc.Solver.Monad.EqualCtList
+ GHC.Tc.Solver.Monad: lookupFamAppCache :: TyCon -> [Type] -> TcS (Maybe (TcCoercion, TcType))
+ GHC.Tc.Solver.Monad: lookupFamAppInert :: TyCon -> [Type] -> TcS (Maybe (TcCoercion, TcType, CtFlavourRole))
+ GHC.Tc.Solver.Monad: newtype EqualCtList
+ GHC.Tc.Solver.Monad: resetUnificationFlag :: TcS Bool
+ GHC.Tc.Solver.Monad: rewriterView :: TcType -> Maybe TcType
+ GHC.Tc.Solver.Monad: setUnificationFlag :: TcLevel -> TcS ()
+ GHC.Tc.Solver.Monad: wrapTcS :: TcM a -> TcS a
+ GHC.Tc.Solver.Rewrite: instance GHC.Base.Applicative GHC.Tc.Solver.Rewrite.RewriteM
+ GHC.Tc.Solver.Rewrite: instance GHC.Base.Functor GHC.Tc.Solver.Rewrite.RewriteM
+ GHC.Tc.Solver.Rewrite: instance GHC.Base.Monad GHC.Tc.Solver.Rewrite.RewriteM
+ GHC.Tc.Solver.Rewrite: instance GHC.Driver.Session.HasDynFlags GHC.Tc.Solver.Rewrite.RewriteM
+ GHC.Tc.Solver.Rewrite: rewrite :: CtEvidence -> TcType -> TcS (Xi, TcCoercion)
+ GHC.Tc.Solver.Rewrite: rewriteArgsNom :: CtEvidence -> TyCon -> [TcType] -> TcS ([Xi], [TcCoercion])
+ GHC.Tc.Solver.Rewrite: rewriteKind :: CtLoc -> CtFlavour -> TcType -> TcS (Xi, TcCoercionN)
+ GHC.Tc.Solver.Rewrite: rewriteType :: CtLoc -> TcType -> TcS TcType
+ GHC.Tc.TyCl: DDataInstance :: Type -> DataDeclInfo
+ GHC.Tc.TyCl: DDataType :: DataDeclInfo
+ GHC.Tc.TyCl: data DataDeclInfo
+ GHC.Tc.Utils.Backpack: implicitRequirementsShallow :: HscEnv -> [(Maybe FastString, Located ModuleName)] -> IO ([ModuleName], [InstantiatedUnit])
+ GHC.Tc.Utils.Monad: NoExtraConstraint :: IsExtraConstraint
+ GHC.Tc.Utils.Monad: YesExtraConstraint :: IsExtraConstraint
+ GHC.Tc.Utils.Monad: data IsExtraConstraint
+ GHC.Tc.Utils.Monad: instance GHC.Utils.Outputable.Outputable GHC.Tc.Utils.Monad.IsExtraConstraint
+ GHC.Tc.Utils.TcMType: newCycleBreakerTyVar :: TcKind -> TcM TcTyVar
+ GHC.Tc.Utils.TcMType: promoteMetaTyVarTo :: TcLevel -> TcTyVar -> TcM Bool
+ GHC.Tc.Utils.Unify: CTE_Bad :: CheckTyEqResult
+ GHC.Tc.Utils.Unify: CTE_HoleBlocker :: CheckTyEqResult
+ GHC.Tc.Utils.Unify: CTE_OK :: CheckTyEqResult
+ GHC.Tc.Utils.Unify: CTE_Occurs :: CheckTyEqResult
+ GHC.Tc.Utils.Unify: NoTypeFamilies :: AreTypeFamiliesOK
+ GHC.Tc.Utils.Unify: YesTypeFamilies :: AreTypeFamiliesOK
+ GHC.Tc.Utils.Unify: checkTyFamEq :: DynFlags -> TyCon -> [TcType] -> TcType -> CheckTyEqResult
+ GHC.Tc.Utils.Unify: checkTyVarEq :: DynFlags -> AreTypeFamiliesOK -> TcTyVar -> TcType -> CheckTyEqResult
+ GHC.Tc.Utils.Unify: checkTypeEq :: DynFlags -> AreTypeFamiliesOK -> CanEqLHS -> TcType -> CheckTyEqResult
+ GHC.Tc.Utils.Unify: data AreTypeFamiliesOK
+ GHC.Tc.Utils.Unify: data CheckTyEqResult
+ GHC.Tc.Utils.Unify: instance GHC.Base.Monoid GHC.Tc.Utils.Unify.CheckTyEqResult
+ GHC.Tc.Utils.Unify: instance GHC.Base.Semigroup GHC.Tc.Utils.Unify.CheckTyEqResult
+ GHC.Tc.Utils.Unify: instance GHC.Classes.Eq GHC.Tc.Utils.Unify.AreTypeFamiliesOK
+ GHC.Tc.Utils.Unify: instance GHC.Utils.Outputable.Outputable GHC.Tc.Utils.Unify.AreTypeFamiliesOK
+ GHC.Tc.Utils.Unify: instance GHC.Utils.Outputable.Outputable GHC.Tc.Utils.Unify.CheckTyEqResult
- GHC: DynFlags :: GhcMode -> GhcLink -> !Backend -> {-# UNPACK #-} !GhcNameVersion -> {-# UNPACK #-} !FileSettings -> Platform -> {-# UNPACK #-} !ToolSettings -> {-# UNPACK #-} !PlatformMisc -> [(String, String)] -> LlvmConfig -> Int -> Int -> Int -> Int -> Int -> Maybe String -> Maybe String -> [Int] -> Maybe Int -> Bool -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Int -> Int -> Int -> Maybe Int -> Maybe Int -> Int -> Word -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Bool -> Maybe Int -> Int -> [FilePath] -> ModuleName -> Maybe String -> IntWithInf -> IntWithInf -> UnitId -> Maybe UnitId -> [(ModuleName, Module)] -> Ways -> Maybe (String, Int) -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> String -> String -> String -> String -> IORef Bool -> String -> String -> Maybe String -> Maybe String -> Maybe String -> DynLibLoader -> !Bool -> Maybe FilePath -> Maybe FilePath -> [Option] -> IncludeSpecs -> [String] -> [String] -> [String] -> Maybe String -> RtsOptsEnabled -> Bool -> String -> [ModuleName] -> [(ModuleName, String)] -> [String] -> Hooks -> FilePath -> Bool -> Bool -> [ModuleName] -> [String] -> [PackageDBFlag] -> [IgnorePackageFlag] -> [PackageFlag] -> [PackageFlag] -> [TrustFlag] -> Maybe FilePath -> Maybe [UnitDatabase UnitId] -> UnitState -> IORef FilesToClean -> IORef (Map FilePath FilePath) -> IORef Int -> IORef (Set FilePath) -> EnumSet DumpFlag -> EnumSet GeneralFlag -> EnumSet WarningFlag -> EnumSet WarningFlag -> Maybe Language -> SafeHaskellMode -> Bool -> Bool -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> [OnOff Extension] -> EnumSet Extension -> !UnfoldingOpts -> Int -> Int -> LogAction -> DumpAction -> TraceAction -> FlushOut -> FlushErr -> Maybe FilePath -> Maybe String -> [String] -> Int -> Int -> Bool -> OverridingBool -> Bool -> Scheme -> ProfAuto -> [CallerCcFilter] -> Maybe String -> IORef (ModuleEnv Int) -> Maybe SseVersion -> Maybe BmiVersion -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> IORef (Maybe LinkerInfo) -> IORef (Maybe CompilerInfo) -> Int -> Int -> Int -> Bool -> Maybe Int -> Int -> Int -> Weights -> DynFlags
+ GHC: DynFlags :: GhcMode -> GhcLink -> !Backend -> {-# UNPACK #-} !GhcNameVersion -> {-# UNPACK #-} !FileSettings -> Platform -> {-# UNPACK #-} !ToolSettings -> {-# UNPACK #-} !PlatformMisc -> [(String, String)] -> LlvmConfig -> Int -> Int -> Int -> Int -> Int -> Maybe String -> Maybe String -> [Int] -> Maybe Int -> Bool -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Int -> Int -> Int -> Maybe Int -> Maybe Int -> Int -> Word -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Bool -> Maybe Int -> Int -> [FilePath] -> ModuleName -> Maybe String -> IntWithInf -> IntWithInf -> UnitId -> Maybe UnitId -> [(ModuleName, Module)] -> Ways -> Maybe (String, Int) -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> String -> String -> String -> String -> IORef Bool -> String -> String -> Maybe String -> Maybe String -> Maybe String -> DynLibLoader -> !Bool -> Maybe FilePath -> Maybe FilePath -> [Option] -> IncludeSpecs -> [String] -> [String] -> [String] -> Maybe String -> RtsOptsEnabled -> Bool -> String -> [ModuleName] -> [(ModuleName, String)] -> [String] -> Hooks -> FilePath -> Bool -> Bool -> [ModuleName] -> [String] -> [PackageDBFlag] -> [IgnorePackageFlag] -> [PackageFlag] -> [PackageFlag] -> [TrustFlag] -> Maybe FilePath -> IORef FilesToClean -> IORef (Map FilePath FilePath) -> IORef Int -> IORef (Set FilePath) -> EnumSet DumpFlag -> EnumSet GeneralFlag -> EnumSet WarningFlag -> EnumSet WarningFlag -> Maybe Language -> SafeHaskellMode -> Bool -> Bool -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> [OnOff Extension] -> EnumSet Extension -> !UnfoldingOpts -> Int -> Int -> LogAction -> DumpAction -> TraceAction -> FlushOut -> FlushErr -> Maybe FilePath -> Maybe String -> [String] -> Int -> Int -> Bool -> OverridingBool -> Bool -> Scheme -> ProfAuto -> [CallerCcFilter] -> Maybe String -> IORef (ModuleEnv Int) -> Maybe SseVersion -> Maybe BmiVersion -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> IORef (Maybe LinkerInfo) -> IORef (Maybe CompilerInfo) -> Int -> Int -> Int -> Bool -> Maybe Int -> Int -> Int -> Weights -> DynFlags
- GHC: cyclicModuleErr :: [ModSummary] -> SDoc
+ GHC: cyclicModuleErr :: [ModuleGraphNode] -> SDoc
- GHC: mkModuleGraph :: [ModSummary] -> ModuleGraph
+ GHC: mkModuleGraph :: [ExtendedModSummary] -> ModuleGraph
- GHC: topSortModuleGraph :: Bool -> ModuleGraph -> Maybe ModuleName -> [SCC ModSummary]
+ GHC: topSortModuleGraph :: Bool -> ModuleGraph -> Maybe ModuleName -> [SCC ModuleGraphNode]
- GHC.Cmm.Parser: parseCmmFile :: DynFlags -> FilePath -> IO (Bag Warning, Bag Error, Maybe CmmGroup)
+ GHC.Cmm.Parser: parseCmmFile :: DynFlags -> HomeUnit -> FilePath -> IO (Bag PsWarning, Bag PsError, Maybe CmmGroup)
- GHC.Cmm.Parser.Monad: PD :: (DynFlags -> PState -> ParseResult a) -> PD a
+ GHC.Cmm.Parser.Monad: PD :: (DynFlags -> HomeUnit -> PState -> ParseResult a) -> PD a
- GHC.Cmm.Parser.Monad: [unPD] :: PD a -> DynFlags -> PState -> ParseResult a
+ GHC.Cmm.Parser.Monad: [unPD] :: PD a -> DynFlags -> HomeUnit -> PState -> ParseResult a
- GHC.Cmm.Parser.Monad: failMsgPD :: (SrcSpan -> Error) -> PD a
+ GHC.Cmm.Parser.Monad: failMsgPD :: (SrcSpan -> PsError) -> PD a
- GHC.Core.Opt.DmdAnal: dmdAnalProgram :: DmdAnalOpts -> FamInstEnvs -> CoreProgram -> CoreProgram
+ GHC.Core.Opt.DmdAnal: dmdAnalProgram :: DmdAnalOpts -> FamInstEnvs -> [CoreRule] -> CoreProgram -> CoreProgram
- GHC.Core.Opt.WorkWrap.Utils: wantToUnbox :: FamInstEnvs -> Bool -> Type -> Demand -> Maybe ([Demand], DataConAppContext)
+ GHC.Core.Opt.WorkWrap.Utils: wantToUnbox :: FamInstEnvs -> Bool -> Type -> Demand -> Maybe ([Demand], DataConPatContext)
- GHC.Driver.CodeOutput: codeOutput :: DynFlags -> Module -> FilePath -> ModLocation -> ForeignStubs -> [(ForeignSrcLang, FilePath)] -> [UnitId] -> Stream IO RawCmmGroup a -> IO (FilePath, (Bool, Maybe FilePath), [(ForeignSrcLang, FilePath)], a)
+ GHC.Driver.CodeOutput: codeOutput :: DynFlags -> UnitState -> Module -> FilePath -> ModLocation -> ForeignStubs -> [(ForeignSrcLang, FilePath)] -> [UnitId] -> Stream IO RawCmmGroup a -> IO (FilePath, (Bool, Maybe FilePath), [(ForeignSrcLang, FilePath)], a)
- GHC.Driver.CodeOutput: outputForeignStubs :: DynFlags -> Module -> ModLocation -> ForeignStubs -> IO (Bool, Maybe FilePath)
+ GHC.Driver.CodeOutput: outputForeignStubs :: DynFlags -> UnitState -> Module -> ModLocation -> ForeignStubs -> IO (Bool, Maybe FilePath)
- GHC.Driver.Main: type Messager = HscEnv -> (Int, Int) -> RecompileRequired -> ModSummary -> IO ()
+ GHC.Driver.Main: type Messager = HscEnv -> (Int, Int) -> RecompileRequired -> ModuleGraphNode -> IO ()
- GHC.Driver.Make: cyclicModuleErr :: [ModSummary] -> SDoc
+ GHC.Driver.Make: cyclicModuleErr :: [ModuleGraphNode] -> SDoc
- GHC.Driver.Make: downsweep :: HscEnv -> [ModSummary] -> [ModuleName] -> Bool -> IO [Either ErrorMessages ModSummary]
+ GHC.Driver.Make: downsweep :: HscEnv -> [ExtendedModSummary] -> [ModuleName] -> Bool -> IO [Either ErrorMessages ExtendedModSummary]
- GHC.Driver.Make: moduleGraphNodes :: Bool -> [ModSummary] -> (Graph SummaryNode, ModuleNameWithIsBoot -> Maybe SummaryNode)
+ GHC.Driver.Make: moduleGraphNodes :: Bool -> [ModuleGraphNode] -> (Graph SummaryNode, NodeKey -> Maybe SummaryNode)
- GHC.Driver.Make: noModError :: DynFlags -> SrcSpan -> ModuleName -> FindResult -> ErrMsg
+ GHC.Driver.Make: noModError :: HscEnv -> SrcSpan -> ModuleName -> FindResult -> ErrMsg
- GHC.Driver.Make: summariseModule :: HscEnv -> NodeMap ModSummary -> IsBootInterface -> Located ModuleName -> Bool -> Maybe (StringBuffer, UTCTime) -> [ModuleName] -> IO (Maybe (Either ErrorMessages ModSummary))
+ GHC.Driver.Make: summariseModule :: HscEnv -> ModNodeMap ExtendedModSummary -> IsBootInterface -> Located ModuleName -> Bool -> Maybe (StringBuffer, UTCTime) -> [ModuleName] -> IO (Maybe (Either ErrorMessages ExtendedModSummary))
- GHC.Driver.Make: topSortModuleGraph :: Bool -> ModuleGraph -> Maybe ModuleName -> [SCC ModSummary]
+ GHC.Driver.Make: topSortModuleGraph :: Bool -> ModuleGraph -> Maybe ModuleName -> [SCC ModuleGraphNode]
- GHC.Driver.Make: type SummaryNode = Node Int ModSummary
+ GHC.Driver.Make: type SummaryNode = Node Int ModuleGraphNode
- GHC.Driver.Pipeline: checkLinkInfo :: DynFlags -> [UnitId] -> FilePath -> IO Bool
+ GHC.Driver.Pipeline: checkLinkInfo :: DynFlags -> UnitEnv -> [UnitId] -> FilePath -> IO Bool
- GHC.Driver.Pipeline: doCpp :: DynFlags -> Bool -> FilePath -> FilePath -> IO ()
+ GHC.Driver.Pipeline: doCpp :: DynFlags -> UnitEnv -> Bool -> FilePath -> FilePath -> IO ()
- GHC.Driver.Pipeline: link :: GhcLink -> DynFlags -> Bool -> HomePackageTable -> IO SuccessFlag
+ GHC.Driver.Pipeline: link :: GhcLink -> DynFlags -> UnitEnv -> Bool -> HomePackageTable -> IO SuccessFlag
- GHC.Driver.Pipeline: linkingNeeded :: DynFlags -> Bool -> [Linkable] -> [UnitId] -> IO Bool
+ GHC.Driver.Pipeline: linkingNeeded :: DynFlags -> UnitEnv -> Bool -> [Linkable] -> [UnitId] -> IO Bool
- GHC.Driver.Pipeline: runPhase :: PhasePlus -> FilePath -> DynFlags -> CompPipeline (PhasePlus, FilePath)
+ GHC.Driver.Pipeline: runPhase :: PhasePlus -> FilePath -> CompPipeline (PhasePlus, FilePath)
- GHC.HsToCore.Types: DsGblEnv :: Module -> FamInstEnv -> PrintUnqualified -> IORef Messages -> (IfGblEnv, IfLclEnv) -> CompleteMatches -> IORef CostCentreState -> DsGblEnv
+ GHC.HsToCore.Types: DsGblEnv :: Module -> FamInstEnv -> GlobalRdrEnv -> PrintUnqualified -> IORef Messages -> (IfGblEnv, IfLclEnv) -> CompleteMatches -> IORef CostCentreState -> DsGblEnv
- GHC.Iface.Load: initExternalPackageState :: HomeUnit -> ExternalPackageState
+ GHC.Iface.Load: initExternalPackageState :: UnitId -> ExternalPackageState
- GHC.Iface.Load: pprModIface :: ModIface -> SDoc
+ GHC.Iface.Load: pprModIface :: UnitState -> ModIface -> SDoc
- GHC.Iface.Load: pprModIfaceSimple :: ModIface -> SDoc
+ GHC.Iface.Load: pprModIfaceSimple :: UnitState -> ModIface -> SDoc
- GHC.Iface.Recomp.Flags: fingerprintDynFlags :: DynFlags -> Module -> (BinHandle -> Name -> IO ()) -> IO Fingerprint
+ GHC.Iface.Recomp.Flags: fingerprintDynFlags :: HscEnv -> Module -> (BinHandle -> Name -> IO ()) -> IO Fingerprint
- GHC.Linker.Dynamic: linkDynLib :: DynFlags -> [String] -> [UnitId] -> IO ()
+ GHC.Linker.Dynamic: linkDynLib :: DynFlags -> UnitEnv -> [String] -> [UnitId] -> IO ()
- GHC.Linker.ExtraObj: checkLinkInfo :: DynFlags -> [UnitId] -> FilePath -> IO Bool
+ GHC.Linker.ExtraObj: checkLinkInfo :: DynFlags -> UnitEnv -> [UnitId] -> FilePath -> IO Bool
- GHC.Linker.ExtraObj: getLinkInfo :: DynFlags -> [UnitId] -> IO String
+ GHC.Linker.ExtraObj: getLinkInfo :: DynFlags -> UnitEnv -> [UnitId] -> IO String
- GHC.Linker.ExtraObj: mkExtraObj :: DynFlags -> Suffix -> String -> IO FilePath
+ GHC.Linker.ExtraObj: mkExtraObj :: DynFlags -> UnitState -> Suffix -> String -> IO FilePath
- GHC.Linker.ExtraObj: mkExtraObjToLinkIntoBinary :: DynFlags -> IO FilePath
+ GHC.Linker.ExtraObj: mkExtraObjToLinkIntoBinary :: DynFlags -> UnitState -> IO FilePath
- GHC.Linker.ExtraObj: mkNoteObjsToLinkIntoBinary :: DynFlags -> [UnitId] -> IO [FilePath]
+ GHC.Linker.ExtraObj: mkNoteObjsToLinkIntoBinary :: DynFlags -> UnitEnv -> [UnitId] -> IO [FilePath]
- GHC.Linker.MacOS: getUnitFrameworkOpts :: DynFlags -> Platform -> [UnitId] -> IO [String]
+ GHC.Linker.MacOS: getUnitFrameworkOpts :: UnitEnv -> [UnitId] -> IO [String]
- GHC.Linker.Static: linkBinary :: DynFlags -> [FilePath] -> [UnitId] -> IO ()
+ GHC.Linker.Static: linkBinary :: DynFlags -> UnitEnv -> [FilePath] -> [UnitId] -> IO ()
- GHC.Linker.Static: linkBinary' :: Bool -> DynFlags -> [FilePath] -> [UnitId] -> IO ()
+ GHC.Linker.Static: linkBinary' :: Bool -> DynFlags -> UnitEnv -> [FilePath] -> [UnitId] -> IO ()
- GHC.Linker.Static: linkStaticLib :: DynFlags -> [String] -> [UnitId] -> IO ()
+ GHC.Linker.Static: linkStaticLib :: DynFlags -> UnitEnv -> [String] -> [UnitId] -> IO ()
- GHC.Linker.Unit: getLibs :: DynFlags -> [UnitId] -> IO [(String, String)]
+ GHC.Linker.Unit: getLibs :: DynFlags -> UnitEnv -> [UnitId] -> IO [(String, String)]
- GHC.Linker.Unit: getUnitLinkOpts :: DynFlags -> [UnitId] -> IO ([String], [String], [String])
+ GHC.Linker.Unit: getUnitLinkOpts :: DynFlags -> UnitEnv -> [UnitId] -> IO ([String], [String], [String])
- GHC.Plugins: CoercionHole :: CoVar -> BlockSubstFlag -> IORef (Maybe Coercion) -> CoercionHole
+ GHC.Plugins: CoercionHole :: CoVar -> IORef (Maybe Coercion) -> CoercionHole
- GHC.Plugins: mkSubCo :: Coercion -> Coercion
+ GHC.Plugins: mkSubCo :: HasDebugCallStack => Coercion -> Coercion
- GHC.Plugins: simplifyArgsWorker :: [TyCoBinder] -> Kind -> TyCoVarSet -> [Role] -> [(Type, Coercion)] -> ([Type], [Coercion], CoercionN)
+ GHC.Plugins: simplifyArgsWorker :: [TyCoBinder] -> Kind -> TyCoVarSet -> [Role] -> [(Type, Coercion)] -> ([Type], [Coercion], MCoercionN)
- GHC.Rename.Env: IncorrectParent :: Name -> Name -> SDoc -> [Name] -> ChildLookupResult
+ GHC.Rename.Env: IncorrectParent :: Name -> GreName -> [Name] -> ChildLookupResult
- GHC.Rename.Utils: mkFieldEnv :: GlobalRdrEnv -> NameEnv (FieldLabelString, Name)
+ GHC.Rename.Utils: mkFieldEnv :: GlobalRdrEnv -> NameEnv (FieldLabelString, Parent)
- GHC.Tc.Gen.HsType: tcHsPatSigType :: UserTypeCtxt -> HsPatSigType GhcRn -> TcM ([(Name, TcTyVar)], [(Name, TcTyVar)], TcType)
+ GHC.Tc.Gen.HsType: tcHsPatSigType :: UserTypeCtxt -> HoleMode -> HsPatSigType GhcRn -> ContextKind -> TcM ([(Name, TcTyVar)], [(Name, TcTyVar)], TcType)
- GHC.Tc.Solver.Monad: IC :: InertEqs -> FunEqMap Ct -> DictMap Ct -> [QCInst] -> DictMap Ct -> Cts -> Int -> InertCans
+ GHC.Tc.Solver.Monad: IC :: InertEqs -> FunEqMap EqualCtList -> DictMap Ct -> [QCInst] -> DictMap Ct -> Cts -> TcLevel -> Bool -> InertCans
- GHC.Tc.Solver.Monad: IS :: InertCans -> [(TcTyVar, TcType)] -> ExactFunEqMap (TcCoercion, TcType, CtFlavour) -> DictMap CtEvidence -> InertSet
+ GHC.Tc.Solver.Monad: IS :: InertCans -> [(TcTyVar, TcType)] -> FunEqMap (TcCoercion, TcType) -> DictMap CtEvidence -> InertSet
- GHC.Tc.Solver.Monad: WL :: [Ct] -> [Ct] -> [Ct] -> Bag Implication -> WorkList
+ GHC.Tc.Solver.Monad: WL :: [Ct] -> [Ct] -> Bag Implication -> WorkList
- GHC.Tc.Solver.Monad: [inert_funeqs] :: InertCans -> FunEqMap Ct
+ GHC.Tc.Solver.Monad: [inert_funeqs] :: InertCans -> FunEqMap EqualCtList
- GHC.Tc.Solver.Monad: findTyEqs :: InertCans -> TyVar -> EqualCtList
+ GHC.Tc.Solver.Monad: findTyEqs :: InertCans -> TyVar -> [Ct]
- GHC.Tc.Solver.Monad: getUnsolvedInerts :: TcS (Bag Implication, Cts, Cts, Cts)
+ GHC.Tc.Solver.Monad: getUnsolvedInerts :: TcS (Bag Implication, Cts)
- GHC.Tc.Solver.Monad: newWantedEq_SI :: BlockSubstFlag -> ShadowInfo -> CtLoc -> Role -> TcType -> TcType -> TcS (CtEvidence, Coercion)
+ GHC.Tc.Solver.Monad: newWantedEq_SI :: ShadowInfo -> CtLoc -> Role -> TcType -> TcType -> TcS (CtEvidence, Coercion)
- GHC.Tc.Solver.Monad: runTcSWithEvBinds :: EvBindsVar -> Bool -> TcS a -> TcM a
+ GHC.Tc.Solver.Monad: runTcSWithEvBinds :: EvBindsVar -> TcS a -> TcM a
- GHC.Tc.TyCl: tcConDecls :: KnotTied TyCon -> NewOrData -> [TyConBinder] -> TcKind -> KnotTied Type -> [LConDecl GhcRn] -> TcM [DataCon]
+ GHC.Tc.TyCl: tcConDecls :: NewOrData -> DataDeclInfo -> KnotTied TyCon -> [TyConBinder] -> TcKind -> [LConDecl GhcRn] -> TcM [DataCon]
- GHC.Tc.Utils.Monad: emitAnonTypeHole :: TcTyVar -> TcM ()
+ GHC.Tc.Utils.Monad: emitAnonTypeHole :: IsExtraConstraint -> TcTyVar -> TcM ()
- GHC.Tc.Utils.Monad: getPrintUnqualified :: DynFlags -> TcRn PrintUnqualified
+ GHC.Tc.Utils.Monad: getPrintUnqualified :: TcRn PrintUnqualified
- GHC.Tc.Utils.TcMType: emitNewExprHole :: OccName -> Id -> Type -> TcM ()
+ GHC.Tc.Utils.TcMType: emitNewExprHole :: OccName -> Type -> TcM HoleExprRef
- GHC.Tc.Utils.TcMType: newCoercionHole :: BlockSubstFlag -> TcPredType -> TcM CoercionHole
+ GHC.Tc.Utils.TcMType: newCoercionHole :: TcPredType -> TcM CoercionHole
- GHC.Tc.Utils.Unify: canSolveByUnification :: TcLevel -> TcTyVar -> TcType -> Bool
+ GHC.Tc.Utils.Unify: canSolveByUnification :: MetaInfo -> TcType -> Bool
- GHC.Tc.Utils.Unify: occCheckForErrors :: DynFlags -> TcTyVar -> Type -> MetaTyVarUpdateResult ()
+ GHC.Tc.Utils.Unify: occCheckForErrors :: DynFlags -> TcTyVar -> Type -> CheckTyEqResult
Files
- compiler/GHC.hs +48/−22
- compiler/GHC/Builtin/Utils.hs +1/−1
- compiler/GHC/ByteCode/Asm.hs +2/−3
- compiler/GHC/ByteCode/Linker.hs +1/−1
- compiler/GHC/Cmm/CommonBlockElim.hs +1/−1
- compiler/GHC/Cmm/LRegSet.hs +53/−0
- compiler/GHC/Cmm/Lexer.x +3/−3
- compiler/GHC/Cmm/Liveness.hs +69/−0
- compiler/GHC/Cmm/Opt.hs +46/−46
- compiler/GHC/Cmm/Parser.y +11/−10
- compiler/GHC/Cmm/Parser/Monad.hs +8/−10
- compiler/GHC/Cmm/Sink.hs +88/−54
- compiler/GHC/Cmm/Utils.hs +5/−3
- compiler/GHC/Core/Map/Expr.hs +392/−0
- compiler/GHC/Core/Opt/CSE.hs +1/−1
- compiler/GHC/Core/Opt/CprAnal.hs +7/−9
- compiler/GHC/Core/Opt/DmdAnal.hs +272/−137
- compiler/GHC/Core/Opt/Pipeline.hs +15/−10
- compiler/GHC/Core/Opt/Simplify.hs +2/−1
- compiler/GHC/Core/Opt/Simplify/Env.hs +2/−3
- compiler/GHC/Core/Opt/WorkWrap.hs +5/−1
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs +175/−115
- compiler/GHC/Core/Tidy.hs +2/−2
- compiler/GHC/CoreToStg/Prep.hs +3/−0
- compiler/GHC/Driver/Backpack.hs +133/−96
- compiler/GHC/Driver/CodeOutput.hs +6/−5
- compiler/GHC/Driver/Main.hs +55/−36
- compiler/GHC/Driver/Make.hs +431/−264
- compiler/GHC/Driver/MakeFile.hs +20/−7
- compiler/GHC/Driver/Pipeline.hs +202/−176
- compiler/GHC/HsToCore.hs +1/−5
- compiler/GHC/HsToCore/Binds.hs +1/−1
- compiler/GHC/HsToCore/Coverage.hs +1/−1
- compiler/GHC/HsToCore/Docs.hs +1/−1
- compiler/GHC/HsToCore/Expr.hs +3/−2
- compiler/GHC/HsToCore/Foreign/Call.hs +2/−1
- compiler/GHC/HsToCore/Match.hs +3/−3
- compiler/GHC/HsToCore/Match/Constructor.hs +2/−2
- compiler/GHC/HsToCore/Monad.hs +18/−15
- compiler/GHC/HsToCore/Pmc/Desugar.hs +1/−1
- compiler/GHC/HsToCore/Pmc/Solver.hs +1/−1
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs +1/−1
- compiler/GHC/HsToCore/Quote.hs +12/−11
- compiler/GHC/HsToCore/Types.hs +4/−0
- compiler/GHC/HsToCore/Usage.hs +4/−6
- compiler/GHC/HsToCore/Utils.hs +8/−1
- compiler/GHC/Iface/Ext/Ast.hs +43/−22
- compiler/GHC/Iface/Ext/Utils.hs +1/−1
- compiler/GHC/Iface/Load.hs +318/−36
- compiler/GHC/Iface/Make.hs +6/−8
- compiler/GHC/Iface/Recomp.hs +5/−5
- compiler/GHC/Iface/Recomp/Flags.hs +7/−4
- compiler/GHC/Iface/Rename.hs +23/−20
- compiler/GHC/Iface/Tidy.hs +1/−4
- compiler/GHC/Linker/Dynamic.hs +13/−19
- compiler/GHC/Linker/ExtraObj.hs +62/−62
- compiler/GHC/Linker/Loader.hs +10/−10
- compiler/GHC/Linker/MacOS.hs +10/−40
- compiler/GHC/Linker/Static.hs +17/−26
- compiler/GHC/Linker/Unit.hs +12/−83
- compiler/GHC/Parser/Utils.hs +58/−0
- compiler/GHC/Rename/Bind.hs +10/−7
- compiler/GHC/Rename/Env.hs +27/−44
- compiler/GHC/Rename/Fixity.hs +1/−1
- compiler/GHC/Rename/HsType.hs +161/−32
- compiler/GHC/Rename/Module.hs +185/−77
- compiler/GHC/Rename/Names.hs +245/−104
- compiler/GHC/Rename/Pat.hs +26/−5
- compiler/GHC/Rename/Splice.hs +1/−1
- compiler/GHC/Rename/Unbound.hs +9/−11
- compiler/GHC/Rename/Utils.hs +28/−29
- compiler/GHC/Runtime/Eval.hs +4/−60
- compiler/GHC/Runtime/Heap/Inspect.hs +1/−1
- compiler/GHC/Runtime/Loader.hs +5/−5
- compiler/GHC/Stg/CSE.hs +5/−1
- compiler/GHC/Tc/Deriv/Generate.hs +113/−8
- compiler/GHC/Tc/Deriv/Utils.hs +2/−2
- compiler/GHC/Tc/Errors.hs +30/−25
- compiler/GHC/Tc/Errors/Hole.hs +10/−6
- compiler/GHC/Tc/Gen/App.hs +68/−20
- compiler/GHC/Tc/Gen/Arrow.hs +16/−12
- compiler/GHC/Tc/Gen/Bind.hs +1/−2
- compiler/GHC/Tc/Gen/Export.hs +86/−86
- compiler/GHC/Tc/Gen/Expr.hs +6/−9
- compiler/GHC/Tc/Gen/Head.hs +15/−30
- compiler/GHC/Tc/Gen/HsType.hs +76/−77
- compiler/GHC/Tc/Gen/Pat.hs +110/−20
- compiler/GHC/Tc/Gen/Rule.hs +1/−1
- compiler/GHC/Tc/Gen/Sig.hs +1/−1
- compiler/GHC/Tc/Gen/Splice.hs +1/−1
- compiler/GHC/Tc/Instance/Family.hs +1/−1
- compiler/GHC/Tc/Instance/Typeable.hs +1/−1
- compiler/GHC/Tc/Module.hs +14/−13
- compiler/GHC/Tc/Plugin.hs +1/−2
- compiler/GHC/Tc/Solver.hs +153/−415
- compiler/GHC/Tc/Solver/Canonical.hs +3214/−2623
- compiler/GHC/Tc/Solver/Flatten.hs +0/−1951
- compiler/GHC/Tc/Solver/Interact.hs +207/−604
- compiler/GHC/Tc/Solver/Monad.hs +3786/−3662
- compiler/GHC/Tc/Solver/Rewrite.hs +1033/−0
- compiler/GHC/Tc/TyCl.hs +284/−178
- compiler/GHC/Tc/TyCl/Instance.hs +90/−10
- compiler/GHC/Tc/TyCl/PatSyn.hs +20/−32
- compiler/GHC/Tc/Utils/Backpack.hs +40/−33
- compiler/GHC/Tc/Utils/Env.hs +36/−1
- compiler/GHC/Tc/Utils/Instantiate.hs +2/−1
- compiler/GHC/Tc/Utils/Monad.hs +25/−17
- compiler/GHC/Tc/Utils/TcMType.hs +71/−95
- compiler/GHC/Tc/Utils/Unify.hs +291/−286
- compiler/GHC/Tc/Utils/Zonk.hs +22/−10
- compiler/GHC/Tc/Validity.hs +0/−6
- compiler/GHC/ThToHs.hs +7/−5
- compiler/GHC/Types/Name/Shape.hs +12/−7
- compiler/GHC/Unit/Finder.hs +5/−248
- ghc-lib.cabal +11/−6
- ghc-lib/stage0/compiler/build/primop-docs.hs-incl +4/−0
- ghc-lib/stage0/lib/ghcversion.h +2/−3
- libraries/ghci/GHCi/CreateBCO.hs +1/−1
- libraries/ghci/GHCi/InfoTable.hsc +20/−61
- libraries/ghci/GHCi/ResolvedBCO.hs +1/−1
compiler/GHC.hs view
@@ -325,6 +325,7 @@ import GHC.Parser.Lexer import GHC.Parser.Annotation import GHC.Parser.Errors.Ppr+import GHC.Parser.Utils import GHC.Iface.Load ( loadSysInterface ) import GHC.Hs@@ -383,6 +384,7 @@ import GHC.Types.SourceFile import GHC.Unit+import GHC.Unit.Env import GHC.Unit.External import GHC.Unit.State import GHC.Unit.Finder@@ -624,8 +626,9 @@ -- (packageFlags dflags). setSessionDynFlags :: GhcMonad m => DynFlags -> m () setSessionDynFlags dflags0 = do- dflags1 <- checkNewDynFlags dflags0- dflags <- liftIO $ initUnits dflags1+ dflags <- checkNewDynFlags dflags0+ hsc_env <- getSession+ (dbs,unit_state,home_unit) <- liftIO $ initUnits dflags (hsc_unit_dbs hsc_env) -- Interpreter interp <- if gopt Opt_ExternalInterpreter dflags@@ -660,12 +663,19 @@ return Nothing #endif + let unit_env = UnitEnv+ { ue_platform = targetPlatform dflags+ , ue_namever = ghcNameVersion dflags+ , ue_home_unit = home_unit+ , ue_units = unit_state+ } modifySession $ \h -> h{ hsc_dflags = dflags , hsc_IC = (hsc_IC h){ ic_dflags = dflags } , hsc_interp = hsc_interp h <|> interp -- we only update the interpreter if there wasn't -- already one set up- , hsc_home_unit = mkHomeUnitFromFlags dflags+ , hsc_unit_env = unit_env+ , hsc_unit_dbs = Just dbs } invalidateModSummaryCache @@ -692,10 +702,21 @@ dflags' <- checkNewDynFlags dflags dflags_prev <- getProgramDynFlags let changed = packageFlagsChanged dflags_prev dflags'- dflags'' <- if changed- then liftIO $ initUnits dflags'- else return dflags'- modifySession $ \h -> h{ hsc_dflags = dflags'' }+ if changed+ then do+ hsc_env <- getSession+ (dbs,unit_state,home_unit) <- liftIO $ initUnits dflags' (hsc_unit_dbs hsc_env)+ let unit_env = UnitEnv+ { ue_platform = targetPlatform dflags'+ , ue_namever = ghcNameVersion dflags'+ , ue_home_unit = home_unit+ , ue_units = unit_state+ }+ modifySession $ \h -> h{ hsc_dflags = dflags'+ , hsc_unit_dbs = Just dbs+ , hsc_unit_env = unit_env+ }+ else modifySession $ \h -> h{ hsc_dflags = dflags' } when invalidate_needed $ invalidateModSummaryCache return changed @@ -1291,11 +1312,7 @@ getPrintUnqual :: GhcMonad m => m PrintUnqualified getPrintUnqual = withSession $ \hsc_env -> do- let dflags = hsc_dflags hsc_env- return $ icPrintUnqual- (unitState dflags)- (hsc_home_unit hsc_env)- (hsc_IC hsc_env)+ return $ icPrintUnqual (hsc_unit_env hsc_env) (hsc_IC hsc_env) -- | Container for information about a 'Module'. data ModuleInfo = ModuleInfo {@@ -1347,6 +1364,18 @@ minf_modBreaks = emptyModBreaks })) +availsToGlobalRdrEnv :: ModuleName -> [AvailInfo] -> GlobalRdrEnv+availsToGlobalRdrEnv mod_name avails+ = mkGlobalRdrEnv (gresFromAvails (Just imp_spec) avails)+ where+ -- We're building a GlobalRdrEnv as if the user imported+ -- all the specified modules into the global interactive module+ imp_spec = ImpSpec { is_decl = decl, is_item = ImpAll}+ decl = ImpDeclSpec { is_mod = mod_name, is_as = mod_name,+ is_qual = False,+ is_dloc = srcLocSpan interactiveSrcLoc }++ getHomeModuleInfo :: HscEnv -> Module -> IO (Maybe ModuleInfo) getHomeModuleInfo hsc_env mdl = case lookupHpt (hsc_HPT hsc_env) (moduleName mdl) of@@ -1370,7 +1399,7 @@ modInfoTopLevelScope :: ModuleInfo -> Maybe [Name] modInfoTopLevelScope minf- = fmap (map gre_name . globalRdrEnvElts) (minf_rdr_env minf)+ = fmap (map greMangledName . globalRdrEnvElts) (minf_rdr_env minf) modInfoExports :: ModuleInfo -> [Name] modInfoExports minf = concatMap availNames $! minf_exports minf@@ -1390,10 +1419,7 @@ ModuleInfo -> m (Maybe PrintUnqualified) -- XXX: returns a Maybe X mkPrintUnqualifiedForModule minf = withSession $ \hsc_env -> do- let dflags = hsc_dflags hsc_env- mk_print_unqual = mkPrintUnqualified- (unitState dflags)- (hsc_home_unit hsc_env)+ let mk_print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) return (fmap mk_print_unqual (minf_rdr_env minf)) modInfoLookupName :: GhcMonad m =>@@ -1620,14 +1646,14 @@ -- using the algorithm that is used for an @import@ declaration. findModule :: GhcMonad m => ModuleName -> Maybe FastString -> m Module findModule mod_name maybe_pkg = withSession $ \hsc_env -> do- let dflags = hsc_dflags hsc_env- home_unit = hsc_home_unit hsc_env+ let dflags = hsc_dflags hsc_env+ home_unit = hsc_home_unit hsc_env case maybe_pkg of Just pkg | not (isHomeUnit home_unit (fsToUnit pkg)) && pkg /= fsLit "this" -> liftIO $ do res <- findImportedModule hsc_env mod_name maybe_pkg case res of Found _ m -> return m- err -> throwOneError $ noModError dflags noSrcSpan mod_name err+ err -> throwOneError $ noModError hsc_env noSrcSpan mod_name err _otherwise -> do home <- lookupLoadedHomeModule mod_name case home of@@ -1637,7 +1663,7 @@ case res of Found loc m | not (isHomeModule home_unit m) -> return m | otherwise -> modNotLoadedError dflags m loc- err -> throwOneError $ noModError dflags noSrcSpan mod_name err+ err -> throwOneError $ noModError hsc_env noSrcSpan mod_name err modNotLoadedError :: DynFlags -> Module -> ModLocation -> IO a modNotLoadedError dflags m loc = throwGhcExceptionIO $ CmdLineError $ showSDoc dflags $@@ -1662,7 +1688,7 @@ res <- findExposedPackageModule hsc_env mod_name Nothing case res of Found _ m -> return m- err -> throwOneError $ noModError (hsc_dflags hsc_env) noSrcSpan mod_name err+ err -> throwOneError $ noModError hsc_env noSrcSpan mod_name err lookupLoadedHomeModule :: GhcMonad m => ModuleName -> m (Maybe Module) lookupLoadedHomeModule mod_name = withSession $ \hsc_env ->
compiler/GHC/Builtin/Utils.hs view
@@ -265,7 +265,7 @@ ghcPrimExports = map (avail . idName) ghcPrimIds ++ map (avail . idName . primOpId) allThePrimOps ++- [ AvailTC n [n] []+ [ availTC n [n] [] | tc <- exposedPrimTyCons, let n = tyConName tc ] ghcPrimDeclDocs :: DeclDocMap
compiler/GHC/ByteCode/Asm.hs view
@@ -41,11 +41,10 @@ import GHC.Core.TyCon import GHC.Data.FastString+import GHC.Data.SizedSeq+ import GHC.StgToCmm.Layout ( ArgRep(..) ) import GHC.Platform---- From iserv-import SizedSeq import Control.Monad import Control.Monad.ST ( runST )
compiler/GHC/ByteCode/Linker.hs view
@@ -26,7 +26,6 @@ import GHCi.RemoteTypes import GHCi.ResolvedBCO import GHCi.BreakArray-import SizedSeq import GHC.Builtin.PrimOps @@ -34,6 +33,7 @@ import GHC.Unit.Module.Name import GHC.Data.FastString+import GHC.Data.SizedSeq import GHC.Utils.Panic import GHC.Utils.Outputable
compiler/GHC/Cmm/CommonBlockElim.hs view
@@ -301,7 +301,7 @@ foldr blockCons code (map CmmTick ticks) -- Group by [Label]--- See Note [Compressed TrieMap] in GHC.Core.Map about the usage of GenMap.+-- See Note [Compressed TrieMap] in GHC.Core.Map.Expr about the usage of GenMap. groupByLabel :: [(Key, DistinctBlocks)] -> [(Key, [DistinctBlocks])] groupByLabel = go (TM.emptyTM :: TM.ListMap (TM.GenMap LabelMap) (Key, [DistinctBlocks]))
+ compiler/GHC/Cmm/LRegSet.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}++module GHC.Cmm.LRegSet (+ LRegSet,+ LRegKey,++ emptyLRegSet,+ nullLRegSet,+ insertLRegSet,+ elemLRegSet,++ deleteFromLRegSet,+ sizeLRegSet,++ plusLRegSet,+ elemsLRegSet+ ) where++import GHC.Prelude+import GHC.Types.Unique+import GHC.Cmm.Expr++import Data.IntSet as IntSet++-- Compact sets for membership tests of local variables.++type LRegSet = IntSet.IntSet+type LRegKey = Int++emptyLRegSet :: LRegSet+emptyLRegSet = IntSet.empty++nullLRegSet :: LRegSet -> Bool+nullLRegSet = IntSet.null++insertLRegSet :: LocalReg -> LRegSet -> LRegSet+insertLRegSet l = IntSet.insert (getKey (getUnique l))++elemLRegSet :: LocalReg -> LRegSet -> Bool+elemLRegSet l = IntSet.member (getKey (getUnique l))++deleteFromLRegSet :: LRegSet -> LocalReg -> LRegSet+deleteFromLRegSet set reg = IntSet.delete (getKey . getUnique $ reg) set++sizeLRegSet :: IntSet -> Int+sizeLRegSet = IntSet.size++plusLRegSet :: IntSet -> IntSet -> IntSet+plusLRegSet = IntSet.union++elemsLRegSet :: IntSet -> [Int]+elemsLRegSet = IntSet.toList
compiler/GHC/Cmm/Lexer.x view
@@ -326,7 +326,7 @@ AlexEOF -> do let span = mkPsSpan loc1 loc1 liftP (setLastToken span 0) return (L span CmmT_EOF)- AlexError (loc2,_) -> liftP $ failLocMsgP (psRealLoc loc1) (psRealLoc loc2) (Error ErrCmmLexer [])+ AlexError (loc2,_) -> liftP $ failLocMsgP (psRealLoc loc1) (psRealLoc loc2) (PsError PsErrCmmLexer []) AlexSkip inp2 _ -> do setInput inp2 lexToken@@ -362,8 +362,8 @@ s' = stepOn s getInput :: PD AlexInput-getInput = PD $ \_ s@PState{ loc=l, buffer=b } -> POk s (l,b)+getInput = PD $ \_ _ s@PState{ loc=l, buffer=b } -> POk s (l,b) setInput :: AlexInput -> PD ()-setInput (l,b) = PD $ \_ s -> POk s{ loc=l, buffer=b } ()+setInput (l,b) = PD $ \_ _ s -> POk s{ loc=l, buffer=b } () }
compiler/GHC/Cmm/Liveness.hs view
@@ -6,9 +6,12 @@ module GHC.Cmm.Liveness ( CmmLocalLive , cmmLocalLiveness+ , cmmLocalLivenessL , cmmGlobalLiveness , liveLattice+ , liveLatticeL , gen_kill+ , gen_killL ) where @@ -22,11 +25,14 @@ import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow import GHC.Cmm.Dataflow.Label+import GHC.Cmm.LRegSet import GHC.Data.Maybe import GHC.Utils.Outputable import GHC.Utils.Panic +import GHC.Types.Unique+ ----------------------------------------------------------------------------- -- Calculating what variables are live on entry to a basic block -----------------------------------------------------------------------------@@ -92,3 +98,66 @@ in mapSingleton (entryLabel eNode) result {-# SPECIALIZE xferLive :: Platform -> TransferFun (CmmLive LocalReg) #-} {-# SPECIALIZE xferLive :: Platform -> TransferFun (CmmLive GlobalReg) #-}++-----------------------------------------------------------------------------+-- | Specialization that only retains the keys for local variables.+--+-- Local variablas are mostly glorified Ints, and some parts of the compiler+-- really don't care about anything but the Int part. So we can avoid some+-- overhead by computing a IntSet instead of a Set LocalReg which (unsurprisingly)+-- is quite a bit faster.+-----------------------------------------------------------------------------++type BlockEntryLivenessL = LabelMap LRegSet++-- | The dataflow lattice+liveLatticeL :: DataflowLattice LRegSet+liveLatticeL = DataflowLattice emptyLRegSet add+ where+ add (OldFact old) (NewFact new) =+ let !join = plusLRegSet old new+ in changedIf (sizeLRegSet join > sizeLRegSet old) join+++cmmLocalLivenessL :: Platform -> CmmGraph -> BlockEntryLivenessL+cmmLocalLivenessL platform graph =+ check $ analyzeCmmBwd liveLatticeL (xferLiveL platform) graph mapEmpty+ where+ entry = g_entry graph+ check facts =+ noLiveOnEntryL entry (expectJust "check" $ mapLookup entry facts) facts++-- | On entry to the procedure, there had better not be any LocalReg's live-in.+noLiveOnEntryL :: BlockId -> LRegSet -> a -> a+noLiveOnEntryL bid in_fact x =+ if nullLRegSet in_fact then x+ else pprPanic "LocalReg's live-in to graph" (ppr bid <+> ppr reg_uniques)+ where+ -- We convert the int's to uniques so that the printing matches that+ -- of registers.+ reg_uniques = map mkUniqueGrimily $ elemsLRegSet in_fact+++++gen_killL+ :: (DefinerOfRegs LocalReg n, UserOfRegs LocalReg n)+ => Platform -> n -> LRegSet -> LRegSet+gen_killL platform node set =+ let !afterKill = foldRegsDefd platform deleteFromLRegSet set node+ in foldRegsUsed platform (flip insertLRegSet) afterKill node+{-# INLINE gen_killL #-}++xferLiveL+ :: ( UserOfRegs LocalReg (CmmNode O O)+ , DefinerOfRegs LocalReg (CmmNode O O)+ , UserOfRegs LocalReg (CmmNode O C)+ , DefinerOfRegs LocalReg (CmmNode O C)+ )+ => Platform -> TransferFun LRegSet+xferLiveL platform (BlockCC eNode middle xNode) fBase =+ let joined = gen_killL platform xNode $! joinOutFacts liveLatticeL xNode fBase+ !result = foldNodesBwdOO (gen_killL platform) middle joined+ in mapSingleton (entryLabel eNode) result++
compiler/GHC/Cmm/Opt.hs view
@@ -58,7 +58,7 @@ -> Maybe CmmExpr cmmMachOpFoldM _ op [CmmLit (CmmInt x rep)]- = Just $ case op of+ = Just $! case op of MO_S_Neg _ -> CmmLit (CmmInt (-x) rep) MO_Not _ -> CmmLit (CmmInt (complement x) rep) @@ -90,13 +90,13 @@ -- but remember to use the signedness from the widening, just in case -- the final conversion is a widen. | rep1 < rep2 && rep2 > rep3 ->- Just $ cmmMachOpFold platform (intconv signed1 rep1 rep3) [x]+ Just $! cmmMachOpFold platform (intconv signed1 rep1 rep3) [x] -- Nested widenings: collapse if the signedness is the same | rep1 < rep2 && rep2 < rep3 && signed1 == signed2 ->- Just $ cmmMachOpFold platform (intconv signed1 rep1 rep3) [x]+ Just $! cmmMachOpFold platform (intconv signed1 rep1 rep3) [x] -- Nested narrowings: collapse | rep1 > rep2 && rep2 > rep3 ->- Just $ cmmMachOpFold platform (MO_UU_Conv rep1 rep3) [x]+ Just $! cmmMachOpFold platform (MO_UU_Conv rep1 rep3) [x] | otherwise -> Nothing where@@ -117,34 +117,34 @@ = case mop of -- for comparisons: don't forget to narrow the arguments before -- comparing, since they might be out of range.- MO_Eq _ -> Just $ CmmLit (CmmInt (if x_u == y_u then 1 else 0) (wordWidth platform))- MO_Ne _ -> Just $ CmmLit (CmmInt (if x_u /= y_u then 1 else 0) (wordWidth platform))+ MO_Eq _ -> Just $! CmmLit (CmmInt (if x_u == y_u then 1 else 0) (wordWidth platform))+ MO_Ne _ -> Just $! CmmLit (CmmInt (if x_u /= y_u then 1 else 0) (wordWidth platform)) - MO_U_Gt _ -> Just $ CmmLit (CmmInt (if x_u > y_u then 1 else 0) (wordWidth platform))- MO_U_Ge _ -> Just $ CmmLit (CmmInt (if x_u >= y_u then 1 else 0) (wordWidth platform))- MO_U_Lt _ -> Just $ CmmLit (CmmInt (if x_u < y_u then 1 else 0) (wordWidth platform))- MO_U_Le _ -> Just $ CmmLit (CmmInt (if x_u <= y_u then 1 else 0) (wordWidth platform))+ MO_U_Gt _ -> Just $! CmmLit (CmmInt (if x_u > y_u then 1 else 0) (wordWidth platform))+ MO_U_Ge _ -> Just $! CmmLit (CmmInt (if x_u >= y_u then 1 else 0) (wordWidth platform))+ MO_U_Lt _ -> Just $! CmmLit (CmmInt (if x_u < y_u then 1 else 0) (wordWidth platform))+ MO_U_Le _ -> Just $! CmmLit (CmmInt (if x_u <= y_u then 1 else 0) (wordWidth platform)) - MO_S_Gt _ -> Just $ CmmLit (CmmInt (if x_s > y_s then 1 else 0) (wordWidth platform))- MO_S_Ge _ -> Just $ CmmLit (CmmInt (if x_s >= y_s then 1 else 0) (wordWidth platform))- MO_S_Lt _ -> Just $ CmmLit (CmmInt (if x_s < y_s then 1 else 0) (wordWidth platform))- MO_S_Le _ -> Just $ CmmLit (CmmInt (if x_s <= y_s then 1 else 0) (wordWidth platform))+ MO_S_Gt _ -> Just $! CmmLit (CmmInt (if x_s > y_s then 1 else 0) (wordWidth platform))+ MO_S_Ge _ -> Just $! CmmLit (CmmInt (if x_s >= y_s then 1 else 0) (wordWidth platform))+ MO_S_Lt _ -> Just $! CmmLit (CmmInt (if x_s < y_s then 1 else 0) (wordWidth platform))+ MO_S_Le _ -> Just $! CmmLit (CmmInt (if x_s <= y_s then 1 else 0) (wordWidth platform)) - MO_Add r -> Just $ CmmLit (CmmInt (x + y) r)- MO_Sub r -> Just $ CmmLit (CmmInt (x - y) r)- MO_Mul r -> Just $ CmmLit (CmmInt (x * y) r)- MO_U_Quot r | y /= 0 -> Just $ CmmLit (CmmInt (x_u `quot` y_u) r)- MO_U_Rem r | y /= 0 -> Just $ CmmLit (CmmInt (x_u `rem` y_u) r)- MO_S_Quot r | y /= 0 -> Just $ CmmLit (CmmInt (x `quot` y) r)- MO_S_Rem r | y /= 0 -> Just $ CmmLit (CmmInt (x `rem` y) r)+ MO_Add r -> Just $! CmmLit (CmmInt (x + y) r)+ MO_Sub r -> Just $! CmmLit (CmmInt (x - y) r)+ MO_Mul r -> Just $! CmmLit (CmmInt (x * y) r)+ MO_U_Quot r | y /= 0 -> Just $! CmmLit (CmmInt (x_u `quot` y_u) r)+ MO_U_Rem r | y /= 0 -> Just $! CmmLit (CmmInt (x_u `rem` y_u) r)+ MO_S_Quot r | y /= 0 -> Just $! CmmLit (CmmInt (x `quot` y) r)+ MO_S_Rem r | y /= 0 -> Just $! CmmLit (CmmInt (x `rem` y) r) - MO_And r -> Just $ CmmLit (CmmInt (x .&. y) r)- MO_Or r -> Just $ CmmLit (CmmInt (x .|. y) r)- MO_Xor r -> Just $ CmmLit (CmmInt (x `xor` y) r)+ MO_And r -> Just $! CmmLit (CmmInt (x .&. y) r)+ MO_Or r -> Just $! CmmLit (CmmInt (x .|. y) r)+ MO_Xor r -> Just $! CmmLit (CmmInt (x `xor` y) r) - MO_Shl r -> Just $ CmmLit (CmmInt (x `shiftL` fromIntegral y) r)- MO_U_Shr r -> Just $ CmmLit (CmmInt (x_u `shiftR` fromIntegral y) r)- MO_S_Shr r -> Just $ CmmLit (CmmInt (x `shiftR` fromIntegral y) r)+ MO_Shl r -> Just $! CmmLit (CmmInt (x `shiftL` fromIntegral y) r)+ MO_U_Shr r -> Just $! CmmLit (CmmInt (x_u `shiftR` fromIntegral y) r)+ MO_S_Shr r -> Just $! CmmLit (CmmInt (x `shiftR` fromIntegral y) r) _ -> Nothing @@ -162,7 +162,7 @@ cmmMachOpFoldM platform op [x@(CmmLit _), y] | not (isLit y) && isCommutableMachOp op- = Just (cmmMachOpFold platform op [y, x])+ = Just $! (cmmMachOpFold platform op [y, x]) -- Turn (a+b)+c into a+(b+c) where possible. Because literals are -- moved to the right, it is more likely that we will find@@ -183,7 +183,7 @@ cmmMachOpFoldM platform mop1 [CmmMachOp mop2 [arg1,arg2], arg3] | mop2 `associates_with` mop1 && not (isLit arg1) && not (isPicReg arg1)- = Just (cmmMachOpFold platform mop2 [arg1, cmmMachOpFold platform mop1 [arg2,arg3]])+ = Just $! (cmmMachOpFold platform mop2 [arg1, cmmMachOpFold platform mop1 [arg2,arg3]]) where MO_Add{} `associates_with` MO_Sub{} = True mop1 `associates_with` mop2 =@@ -192,7 +192,7 @@ -- special case: (a - b) + c ==> a + (c - b) cmmMachOpFoldM platform mop1@(MO_Add{}) [CmmMachOp mop2@(MO_Sub{}) [arg1,arg2], arg3] | not (isLit arg1) && not (isPicReg arg1)- = Just (cmmMachOpFold platform mop1 [arg1, cmmMachOpFold platform mop2 [arg3,arg2]])+ = Just $! (cmmMachOpFold platform mop1 [arg1, cmmMachOpFold platform mop2 [arg3,arg2]]) -- special case: (PicBaseReg + lit) + N ==> PicBaseReg + (lit+N) --@@ -205,27 +205,27 @@ cmmMachOpFoldM _ MO_Add{} [ CmmMachOp op@MO_Add{} [pic, CmmLit lit] , CmmLit (CmmInt n rep) ] | isPicReg pic- = Just $ CmmMachOp op [pic, CmmLit $ cmmOffsetLit lit off ]+ = Just $! CmmMachOp op [pic, CmmLit $ cmmOffsetLit lit off ] where off = fromIntegral (narrowS rep n) -- Make a RegOff if we can cmmMachOpFoldM _ (MO_Add _) [CmmReg reg, CmmLit (CmmInt n rep)]- = Just $ cmmRegOff reg (fromIntegral (narrowS rep n))+ = Just $! cmmRegOff reg (fromIntegral (narrowS rep n)) cmmMachOpFoldM _ (MO_Add _) [CmmRegOff reg off, CmmLit (CmmInt n rep)]- = Just $ cmmRegOff reg (off + fromIntegral (narrowS rep n))+ = Just $! cmmRegOff reg (off + fromIntegral (narrowS rep n)) cmmMachOpFoldM _ (MO_Sub _) [CmmReg reg, CmmLit (CmmInt n rep)]- = Just $ cmmRegOff reg (- fromIntegral (narrowS rep n))+ = Just $! cmmRegOff reg (- fromIntegral (narrowS rep n)) cmmMachOpFoldM _ (MO_Sub _) [CmmRegOff reg off, CmmLit (CmmInt n rep)]- = Just $ cmmRegOff reg (off - fromIntegral (narrowS rep n))+ = Just $! cmmRegOff reg (off - fromIntegral (narrowS rep n)) -- Fold label(+/-)offset into a CmmLit where possible cmmMachOpFoldM _ (MO_Add _) [CmmLit lit, CmmLit (CmmInt i rep)]- = Just $ CmmLit (cmmOffsetLit lit (fromIntegral (narrowU rep i)))+ = Just $! CmmLit (cmmOffsetLit lit (fromIntegral (narrowU rep i))) cmmMachOpFoldM _ (MO_Add _) [CmmLit (CmmInt i rep), CmmLit lit]- = Just $ CmmLit (cmmOffsetLit lit (fromIntegral (narrowU rep i)))+ = Just $! CmmLit (cmmOffsetLit lit (fromIntegral (narrowU rep i))) cmmMachOpFoldM _ (MO_Sub _) [CmmLit lit, CmmLit (CmmInt i rep)]- = Just $ CmmLit (cmmOffsetLit lit (fromIntegral (negate (narrowU rep i))))+ = Just $! CmmLit (cmmOffsetLit lit (fromIntegral (negate (narrowU rep i)))) -- Comparison of literal with widened operand: perform the comparison@@ -245,7 +245,7 @@ -- and the literal fits in the smaller size: i == narrow_fn rep i -- then we can do the comparison at the smaller size- = Just (cmmMachOpFold platform narrow_cmp [x, CmmLit (CmmInt i rep)])+ = Just $! (cmmMachOpFold platform narrow_cmp [x, CmmLit (CmmInt i rep)]) where maybe_conversion (MO_UU_Conv from to) | to > from@@ -320,8 +320,8 @@ MO_Mul _ -> Just x MO_S_Quot _ -> Just x MO_U_Quot _ -> Just x- MO_S_Rem _ -> Just $ CmmLit (CmmInt 0 rep)- MO_U_Rem _ -> Just $ CmmLit (CmmInt 0 rep)+ MO_S_Rem _ -> Just $! CmmLit (CmmInt 0 rep)+ MO_U_Rem _ -> Just $! CmmLit (CmmInt 0 rep) -- Comparisons; trickier -- See Note [Comparison operators]@@ -346,18 +346,18 @@ = case mop of MO_Mul rep | Just p <- exactLog2 n ->- Just (cmmMachOpFold platform (MO_Shl rep) [x, CmmLit (CmmInt p rep)])+ Just $! (cmmMachOpFold platform (MO_Shl rep) [x, CmmLit (CmmInt p rep)]) MO_U_Quot rep | Just p <- exactLog2 n ->- Just (cmmMachOpFold platform (MO_U_Shr rep) [x, CmmLit (CmmInt p rep)])+ Just $! (cmmMachOpFold platform (MO_U_Shr rep) [x, CmmLit (CmmInt p rep)]) MO_U_Rem rep | Just _ <- exactLog2 n ->- Just (cmmMachOpFold platform (MO_And rep) [x, CmmLit (CmmInt (n - 1) rep)])+ Just $! (cmmMachOpFold platform (MO_And rep) [x, CmmLit (CmmInt (n - 1) rep)]) MO_S_Quot rep | Just p <- exactLog2 n, CmmReg _ <- x -> -- We duplicate x in signedQuotRemHelper, hence require -- it is a reg. FIXME: remove this restriction.- Just (cmmMachOpFold platform (MO_S_Shr rep)+ Just $! (cmmMachOpFold platform (MO_S_Shr rep) [signedQuotRemHelper rep p, CmmLit (CmmInt p rep)]) MO_S_Rem rep | Just p <- exactLog2 n,@@ -366,7 +366,7 @@ -- We replace (x `rem` 2^p) by (x - (x `quot` 2^p) * 2^p). -- Moreover, we fuse MO_S_Shr (last operation of MO_S_Quot) -- and MO_S_Shl (multiplication by 2^p) into a single MO_And operation.- Just (cmmMachOpFold platform (MO_Sub rep)+ Just $! (cmmMachOpFold platform (MO_Sub rep) [x, cmmMachOpFold platform (MO_And rep) [signedQuotRemHelper rep p, CmmLit (CmmInt (- n) rep)]]) _ -> Nothing
compiler/GHC/Cmm/Parser.y view
@@ -244,6 +244,7 @@ import GHC.Types.CostCentre import GHC.Types.ForeignCall import GHC.Unit.Module+import GHC.Unit.Home import GHC.Types.Literal import GHC.Types.Unique import GHC.Types.Unique.FM@@ -918,7 +919,7 @@ nameToMachOp :: FastString -> PD (Width -> MachOp) nameToMachOp name = case lookupUFM machOps name of- Nothing -> failMsgPD $ Error (ErrCmmParser (CmmUnknownPrimitive name)) []+ Nothing -> failMsgPD $ PsError (PsErrCmmParser (CmmUnknownPrimitive name)) [] Just m -> return m exprOp :: FastString -> [CmmParse CmmExpr] -> PD (CmmParse CmmExpr)@@ -1080,12 +1081,12 @@ parseSafety "safe" = return PlaySafe parseSafety "unsafe" = return PlayRisky parseSafety "interruptible" = return PlayInterruptible-parseSafety str = failMsgPD $ Error (ErrCmmParser (CmmUnrecognisedSafety str)) []+parseSafety str = failMsgPD $ PsError (PsErrCmmParser (CmmUnrecognisedSafety str)) [] parseCmmHint :: String -> PD ForeignHint parseCmmHint "ptr" = return AddrHint parseCmmHint "signed" = return SignedHint-parseCmmHint str = failMsgPD $ Error (ErrCmmParser (CmmUnrecognisedHint str)) []+parseCmmHint str = failMsgPD $ PsError (PsErrCmmParser (CmmUnrecognisedHint str)) [] -- labels are always pointers, so we might as well infer the hint inferCmmHint :: CmmExpr -> ForeignHint@@ -1104,7 +1105,7 @@ isPtrGlobalReg _ = False happyError :: PD a-happyError = PD $ \_ s -> unP srcParseFail s+happyError = PD $ \_ _ s -> unP srcParseFail s -- ----------------------------------------------------------------------------- -- Statement-level macros@@ -1112,7 +1113,7 @@ stmtMacro :: FastString -> [CmmParse CmmExpr] -> PD (CmmParse ()) stmtMacro fun args_code = do case lookupUFM stmtMacros fun of- Nothing -> failMsgPD $ Error (ErrCmmParser (CmmUnknownMacro fun)) []+ Nothing -> failMsgPD $ PsError (PsErrCmmParser (CmmUnknownMacro fun)) [] Just fcode -> return $ do args <- sequence args_code code (fcode args)@@ -1215,7 +1216,7 @@ = do conv <- case conv_string of "C" -> return CCallConv "stdcall" -> return StdCallConv- _ -> failMsgPD $ Error (ErrCmmParser (CmmUnknownCConv conv_string)) []+ _ -> failMsgPD $ PsError (PsErrCmmParser (CmmUnknownCConv conv_string)) [] return $ do platform <- getPlatform results <- sequence results_code@@ -1293,7 +1294,7 @@ = do platform <- PD.getPlatform case lookupUFM (callishMachOps platform) name of- Nothing -> failMsgPD $ Error (ErrCmmParser (CmmUnknownPrimitive name)) []+ Nothing -> failMsgPD $ PsError (PsErrCmmParser (CmmUnknownPrimitive name)) [] Just f -> return $ do results <- sequence results_code args <- sequence args_code@@ -1447,8 +1448,8 @@ ] where platform = profilePlatform profile -parseCmmFile :: DynFlags -> FilePath -> IO (Bag Warning, Bag Error, Maybe CmmGroup)-parseCmmFile dflags filename = do+parseCmmFile :: DynFlags -> HomeUnit -> FilePath -> IO (Bag PsWarning, Bag PsError, Maybe CmmGroup)+parseCmmFile dflags home_unit filename = do buf <- hGetStringBuffer filename let init_loc = mkRealSrcLoc (mkFastString filename) 1 1@@ -1456,7 +1457,7 @@ init_state = (initParserState opts buf init_loc) { lex_state = [0] } -- reset the lex_state: the Lexer monad leaves some stuff -- in there we don't want.- case unPD cmmParse dflags init_state of+ case unPD cmmParse dflags home_unit init_state of PFailed pst -> do let (warnings,errors) = getMessages pst return (warnings, errors, Nothing)
compiler/GHC/Cmm/Parser/Monad.hs view
@@ -32,7 +32,7 @@ import GHC.Unit.Types import GHC.Unit.Home -newtype PD a = PD { unPD :: DynFlags -> PState -> ParseResult a }+newtype PD a = PD { unPD :: DynFlags -> HomeUnit -> PState -> ParseResult a } instance Functor PD where fmap = liftM@@ -45,22 +45,22 @@ (>>=) = thenPD liftP :: P a -> PD a-liftP (P f) = PD $ \_ s -> f s+liftP (P f) = PD $ \_ _ s -> f s -failMsgPD :: (SrcSpan -> Error) -> PD a+failMsgPD :: (SrcSpan -> PsError) -> PD a failMsgPD = liftP . failMsgP returnPD :: a -> PD a returnPD = liftP . return thenPD :: PD a -> (a -> PD b) -> PD b-(PD m) `thenPD` k = PD $ \d s ->- case m d s of- POk s1 a -> unPD (k a) d s1+(PD m) `thenPD` k = PD $ \d hu s ->+ case m d hu s of+ POk s1 a -> unPD (k a) d hu s1 PFailed s1 -> PFailed s1 instance HasDynFlags PD where- getDynFlags = PD $ \d s -> POk s d+ getDynFlags = PD $ \d _ s -> POk s d getProfile :: PD Profile getProfile = targetProfile <$> getDynFlags@@ -79,6 +79,4 @@ -- | Return the UnitId of the home-unit. This is used to create labels. getHomeUnitId :: PD UnitId-getHomeUnitId = do- dflags <- getDynFlags- pure (homeUnitId (mkHomeUnitFromFlags dflags))+getHomeUnitId = PD $ \_ hu s -> POk s (homeUnitId hu)
compiler/GHC/Cmm/Sink.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}+ module GHC.Cmm.Sink ( cmmSink ) where@@ -8,6 +10,7 @@ import GHC.Cmm import GHC.Cmm.Opt import GHC.Cmm.Liveness+import GHC.Cmm.LRegSet import GHC.Cmm.Utils import GHC.Cmm.Dataflow.Block import GHC.Cmm.Dataflow.Label@@ -16,29 +19,13 @@ import GHC.Platform.Regs import GHC.Platform-import GHC.Types.Unique import GHC.Types.Unique.FM import qualified Data.IntSet as IntSet import Data.List (partition)-import qualified Data.Set as Set import Data.Maybe --- Compact sets for membership tests of local variables.--type LRegSet = IntSet.IntSet--emptyLRegSet :: LRegSet-emptyLRegSet = IntSet.empty--nullLRegSet :: LRegSet -> Bool-nullLRegSet = IntSet.null--insertLRegSet :: LocalReg -> LRegSet -> LRegSet-insertLRegSet l = IntSet.insert (getKey (getUnique l))--elemLRegSet :: LocalReg -> LRegSet -> Bool-elemLRegSet l = IntSet.member (getKey (getUnique l))+import GHC.Exts (inline) -- ----------------------------------------------------------------------------- -- Sinking and inlining@@ -167,8 +154,8 @@ cmmSink :: Platform -> CmmGraph -> CmmGraph cmmSink platform graph = ofBlockList (g_entry graph) $ sink mapEmpty $ blocks where- liveness = cmmLocalLiveness platform graph- getLive l = mapFindWithDefault Set.empty l liveness+ liveness = cmmLocalLivenessL platform graph+ getLive l = mapFindWithDefault emptyLRegSet l liveness blocks = revPostorder graph @@ -188,8 +175,8 @@ -- Annotate the middle nodes with the registers live *after* -- the node. This will help us decide whether we can inline -- an assignment in the current node or not.- live = Set.unions (map getLive succs)- live_middle = gen_kill platform last live+ live = IntSet.unions (map getLive succs)+ live_middle = gen_killL platform last live ann_middles = annotate platform live_middle (blockToList middle) -- Now sink and inline in this block@@ -201,7 +188,7 @@ -- one predecessor), so identify the join points and the set -- of registers live in them. (joins, nonjoins) = partition (`mapMember` join_pts) succs- live_in_joins = Set.unions (map getLive joins)+ live_in_joins = IntSet.unions (map getLive joins) -- We do not want to sink an assignment into multiple branches, -- so identify the set of registers live in multiple successors.@@ -210,26 +197,28 @@ -- now live in multiple branches. init_live_sets = map getLive nonjoins live_in_multi live_sets r =- case filter (Set.member r) live_sets of+ case filter (elemLRegSet r) live_sets of (_one:_two:_) -> True _ -> False -- Now, drop any assignments that we will not sink any further. (dropped_last, assigs'') = dropAssignments platform drop_if init_live_sets assigs' + drop_if :: (LocalReg, CmmExpr, AbsMem)+ -> [LRegSet] -> (Bool, [LRegSet]) drop_if a@(r,rhs,_) live_sets = (should_drop, live_sets') where should_drop = conflicts platform a final_last || not (isTrivial platform rhs) && live_in_multi live_sets r- || r `Set.member` live_in_joins+ || r `elemLRegSet` live_in_joins live_sets' | should_drop = live_sets | otherwise = map upd live_sets - upd set | r `Set.member` set = set `Set.union` live_rhs+ upd set | r `elemLRegSet` set = set `IntSet.union` live_rhs | otherwise = set - live_rhs = foldRegsUsed platform extendRegSet emptyRegSet rhs+ live_rhs = foldRegsUsed platform (flip insertLRegSet) emptyLRegSet rhs final_middle = foldl' blockSnoc middle' dropped_last @@ -266,9 +255,9 @@ -- -- annotate each node with the set of registers live *after* the node ---annotate :: Platform -> LocalRegSet -> [CmmNode O O] -> [(LocalRegSet, CmmNode O O)]+annotate :: Platform -> LRegSet -> [CmmNode O O] -> [(LRegSet, CmmNode O O)] annotate platform live nodes = snd $ foldr ann (live,[]) nodes- where ann n (live,nodes) = (gen_kill platform n live, (live,n) : nodes)+ where ann n (live,nodes) = (gen_killL platform n live, (live,n) : nodes) -- -- Find the blocks that have multiple successors (join points)@@ -285,13 +274,13 @@ -- filter the list of assignments to remove any assignments that -- are not live in a continuation. ---filterAssignments :: Platform -> LocalRegSet -> Assignments -> Assignments+filterAssignments :: Platform -> LRegSet -> Assignments -> Assignments filterAssignments platform live assigs = reverse (go assigs []) where go [] kept = kept go (a@(r,_,_):as) kept | needed = go as (a:kept) | otherwise = go as kept where- needed = r `Set.member` live+ needed = r `elemLRegSet` live || any (conflicts platform a) (map toNode kept) -- Note that we must keep assignments that are -- referred to by other assignments we have@@ -312,7 +301,7 @@ -- walk :: Platform- -> [(LocalRegSet, CmmNode O O)] -- nodes of the block, annotated with+ -> [(LRegSet, CmmNode O O)] -- nodes of the block, annotated with -- the set of registers live *after* -- this node. @@ -366,11 +355,11 @@ -- out of inlining, but the inliner will see that r is live -- after the instruction and choose not to inline r in the rhs. ---shouldDiscard :: CmmNode e x -> LocalRegSet -> Bool+shouldDiscard :: CmmNode e x -> LRegSet -> Bool shouldDiscard node live = case node of CmmAssign r (CmmReg r') | r == r' -> True- CmmAssign (CmmLocal r) _ -> not (r `Set.member` live)+ CmmAssign (CmmLocal r) _ -> not (r `elemLRegSet` live) _otherwise -> False @@ -403,8 +392,9 @@ -- inlining opens up opportunities for doing so. tryToInline- :: Platform- -> LocalRegSet -- set of registers live after this+ :: forall x. Platform+ -> LRegSet -- set of registers live after this+ -- -> LocalRegSet -- set of registers live after this -- node. We cannot inline anything -- that is live after the node, unless -- it is small enough to duplicate.@@ -415,43 +405,50 @@ , Assignments -- Remaining assignments ) -tryToInline platform live node assigs = go usages node emptyLRegSet assigs+tryToInline platform liveAfter node assigs =+ -- pprTrace "tryToInline assig length:" (ppr $ length assigs) $+ go usages liveAfter node emptyLRegSet assigs where usages :: UniqFM LocalReg Int -- Maps each LocalReg to a count of how often it is used usages = foldLocalRegsUsed platform addUsage emptyUFM node - go _usages node _skipped [] = (node, [])+ go :: UniqFM LocalReg Int -> LRegSet -> CmmNode O x -> LRegSet -> Assignments+ -> (CmmNode O x, Assignments)+ go _usages _live node _skipped [] = (node, []) - go usages node skipped (a@(l,rhs,_) : rest)- | cannot_inline = dont_inline- | occurs_none = discard -- Note [discard during inlining]- | occurs_once = inline_and_discard- | isTrivial platform rhs = inline_and_keep- | otherwise = dont_inline+ go usages live node skipped (a@(l,rhs,_) : rest)+ | cannot_inline = dont_inline+ | occurs_none = discard -- Note [discard during inlining]+ | occurs_once = inline_and_discard+ | isTrivial platform rhs = inline_and_keep+ | otherwise = dont_inline where- inline_and_discard = go usages' inl_node skipped rest+ inline_and_discard = go usages' live inl_node skipped rest where usages' = foldLocalRegsUsed platform addUsage usages rhs - discard = go usages node skipped rest+ discard = go usages live node skipped rest dont_inline = keep node -- don't inline the assignment, keep it inline_and_keep = keep inl_node -- inline the assignment, keep it + keep :: CmmNode O x -> (CmmNode O x, Assignments) keep node' = (final_node, a : rest')- where (final_node, rest') = go usages' node' (insertLRegSet l skipped) rest- usages' = foldLocalRegsUsed platform (\m r -> addToUFM m r 2)- usages rhs- -- we must not inline anything that is mentioned in the RHS- -- of a binding that we have already skipped, so we set the- -- usages of the regs on the RHS to 2.+ where (final_node, rest') = go usages live' node' (insertLRegSet l skipped) rest + -- Avoid discarding of assignments to vars on the rhs.+ -- See Note [Keeping assignemnts mentioned in skipped RHSs]+ -- usages' = foldLocalRegsUsed platform (\m r -> addToUFM m r 2)+ -- usages rhs+ live' = inline foldLocalRegsUsed platform (\m r -> insertLRegSet r m)+ live rhs+ cannot_inline = skipped `regsUsedIn` rhs -- Note [dependent assignments] || l `elemLRegSet` skipped || not (okToInline platform rhs node) -- How often is l used in the current node. l_usages = lookupUFM usages l- l_live = l `elemRegSet` live+ l_live = l `elemLRegSet` live occurs_once = not l_live && l_usages == Just 1 occurs_none = not l_live && l_usages == Nothing@@ -467,7 +464,28 @@ inl_exp (CmmMachOp op args) = cmmMachOpFold platform op args inl_exp other = other +{- Note [Keeping assignemnts mentioned in skipped RHSs]+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + If we have to assignments: [z = y, y = e1] and we skip+ z we *must* retain the assignment y = e1. This is because+ we might inline "z = y" into another node later on so we+ must ensure y is still defined at this point.++ If we dropped the assignment of "y = e1" then we would end up+ referencing a variable which hasn't been mentioned after+ inlining.++ We use a hack to do this.++ We pretend the regs from the rhs are live after the current+ node. Since we only discard assignments to variables+ which are dead after the current block this prevents discarding of the+ assignment. It still allows inlining should e1 be a trivial rhs+ however.++-}+ {- Note [improveConditional] cmmMachOpFold tries to simplify conditionals to turn things like@@ -610,18 +628,34 @@ -- (7) otherwise, no conflict | otherwise = False +{- Note [Inlining foldRegsDefd]+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~++ foldRegsDefd is, after optimization, *not* a small function so+ it's only marked INLINEABLE, but not INLINE.++ However in some specific cases we call it *very* often making it+ important to avoid the overhead of allocating the folding function.++ So we simply force inlining via the magic inline function.+ For T3294 this improves allocation with -O by ~1%.++-}+ -- Returns True if node defines any global registers that are used in the -- Cmm expression globalRegistersConflict :: Platform -> CmmExpr -> CmmNode e x -> Bool globalRegistersConflict platform expr node =- foldRegsDefd platform (\b r -> b || regUsedIn platform (CmmGlobal r) expr)+ -- See Note [Inlining foldRegsDefd]+ inline foldRegsDefd platform (\b r -> b || regUsedIn platform (CmmGlobal r) expr) False node -- Returns True if node defines any local registers that are used in the -- Cmm expression localRegistersConflict :: Platform -> CmmExpr -> CmmNode e x -> Bool localRegistersConflict platform expr node =- foldRegsDefd platform (\b r -> b || regUsedIn platform (CmmLocal r) expr)+ -- See Note [Inlining foldRegsDefd]+ inline foldRegsDefd platform (\b r -> b || regUsedIn platform (CmmLocal r) expr) False node -- Note [Sinking and calls]
compiler/GHC/Cmm/Utils.hs view
@@ -264,9 +264,11 @@ CmmStackSlot area off -> CmmStackSlot area (off - byte_off) -- note stack area offsets increase towards lower addresses CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt byte_off1 _rep)]- -> CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt (byte_off1 + toInteger byte_off) rep)]- _ -> CmmMachOp (MO_Add width) [e, CmmLit (CmmInt (toInteger byte_off) width)]- where width = cmmExprWidth platform e+ -> let !lit_off = (byte_off1 + toInteger byte_off)+ in CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt lit_off rep)]+ _ -> let !width = cmmExprWidth platform e+ in+ CmmMachOp (MO_Add width) [e, CmmLit (CmmInt (toInteger byte_off) width)] -- Smart constructor for CmmRegOff. Same caveats as cmmOffset above. cmmRegOff :: CmmReg -> Int -> CmmExpr
+ compiler/GHC/Core/Map/Expr.hs view
@@ -0,0 +1,392 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++{-+(c) The University of Glasgow 2006+(c) The GRASP/AQUA Project, Glasgow University, 1992-1998+-}++{-# OPTIONS_GHC -Wno-orphans #-}+ -- Eq (DeBruijn CoreExpr) and Eq (DeBruijn CoreAlt)++module GHC.Core.Map.Expr (+ -- * Maps over Core expressions+ CoreMap, emptyCoreMap, extendCoreMap, lookupCoreMap, foldCoreMap,+ -- * 'TrieMap' class reexports+ TrieMap(..), insertTM, deleteTM,+ lkDFreeVar, xtDFreeVar,+ lkDNamed, xtDNamed,+ (>.>), (|>), (|>>),+ ) where++#include "GhclibHsVersions.h"++import GHC.Prelude++import GHC.Data.TrieMap+import GHC.Core.Map.Type+import GHC.Core+import GHC.Core.Type+import GHC.Types.Var++import GHC.Utils.Misc+import GHC.Utils.Outputable++import qualified Data.Map as Map+import GHC.Types.Name.Env+import Control.Monad( (>=>) )++{-+This module implements TrieMaps over Core related data structures+like CoreExpr or Type. It is built on the Tries from the TrieMap+module.++The code is very regular and boilerplate-like, but there is+some neat handling of *binders*. In effect they are deBruijn+numbered on the fly.+++-}++----------------------+-- Recall that+-- Control.Monad.(>=>) :: (a -> Maybe b) -> (b -> Maybe c) -> a -> Maybe c++-- The CoreMap makes heavy use of GenMap. However the CoreMap Types are not+-- known when defining GenMap so we can only specialize them here.++{-# SPECIALIZE lkG :: Key CoreMapX -> CoreMapG a -> Maybe a #-}+{-# SPECIALIZE xtG :: Key CoreMapX -> XT a -> CoreMapG a -> CoreMapG a #-}+{-# SPECIALIZE mapG :: (a -> b) -> CoreMapG a -> CoreMapG b #-}+{-# SPECIALIZE fdG :: (a -> b -> b) -> CoreMapG a -> b -> b #-}+++{-+************************************************************************+* *+ CoreMap+* *+************************************************************************+-}++{-+Note [Binders]+~~~~~~~~~~~~~~+ * In general we check binders as late as possible because types are+ less likely to differ than expression structure. That's why+ cm_lam :: CoreMapG (TypeMapG a)+ rather than+ cm_lam :: TypeMapG (CoreMapG a)++ * We don't need to look at the type of some binders, notably+ - the case binder in (Case _ b _ _)+ - the binders in an alternative+ because they are totally fixed by the context++Note [Empty case alternatives]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+* For a key (Case e b ty (alt:alts)) we don't need to look the return type+ 'ty', because every alternative has that type.++* For a key (Case e b ty []) we MUST look at the return type 'ty', because+ otherwise (Case (error () "urk") _ Int []) would compare equal to+ (Case (error () "urk") _ Bool [])+ which is utterly wrong (#6097)++We could compare the return type regardless, but the wildly common case+is that it's unnecessary, so we have two fields (cm_case and cm_ecase)+for the two possibilities. Only cm_ecase looks at the type.++See also Note [Empty case alternatives] in GHC.Core.+-}++-- | @CoreMap a@ is a map from 'CoreExpr' to @a@. If you are a client, this+-- is the type you want.+newtype CoreMap a = CoreMap (CoreMapG a)++instance TrieMap CoreMap where+ type Key CoreMap = CoreExpr+ emptyTM = CoreMap emptyTM+ lookupTM k (CoreMap m) = lookupTM (deBruijnize k) m+ alterTM k f (CoreMap m) = CoreMap (alterTM (deBruijnize k) f m)+ foldTM k (CoreMap m) = foldTM k m+ mapTM f (CoreMap m) = CoreMap (mapTM f m)+ filterTM f (CoreMap m) = CoreMap (filterTM f m)++-- | @CoreMapG a@ is a map from @DeBruijn CoreExpr@ to @a@. The extended+-- key makes it suitable for recursive traversal, since it can track binders,+-- but it is strictly internal to this module. If you are including a 'CoreMap'+-- inside another 'TrieMap', this is the type you want.+type CoreMapG = GenMap CoreMapX++-- | @CoreMapX a@ is the base map from @DeBruijn CoreExpr@ to @a@, but without+-- the 'GenMap' optimization.+data CoreMapX a+ = CM { cm_var :: VarMap a+ , cm_lit :: LiteralMap a+ , cm_co :: CoercionMapG a+ , cm_type :: TypeMapG a+ , cm_cast :: CoreMapG (CoercionMapG a)+ , cm_tick :: CoreMapG (TickishMap a)+ , cm_app :: CoreMapG (CoreMapG a)+ , cm_lam :: CoreMapG (BndrMap a) -- Note [Binders]+ , cm_letn :: CoreMapG (CoreMapG (BndrMap a))+ , cm_letr :: ListMap CoreMapG (CoreMapG (ListMap BndrMap a))+ , cm_case :: CoreMapG (ListMap AltMap a)+ , cm_ecase :: CoreMapG (TypeMapG a) -- Note [Empty case alternatives]+ }++instance Eq (DeBruijn CoreExpr) where+ D env1 e1 == D env2 e2 = go e1 e2 where+ go (Var v1) (Var v2)+ = case (lookupCME env1 v1, lookupCME env2 v2) of+ (Just b1, Just b2) -> b1 == b2+ (Nothing, Nothing) -> v1 == v2+ _ -> False+ go (Lit lit1) (Lit lit2) = lit1 == lit2+ go (Type t1) (Type t2) = D env1 t1 == D env2 t2+ go (Coercion co1) (Coercion co2) = D env1 co1 == D env2 co2+ go (Cast e1 co1) (Cast e2 co2) = D env1 co1 == D env2 co2 && go e1 e2+ go (App f1 a1) (App f2 a2) = go f1 f2 && go a1 a2+ -- This seems a bit dodgy, see 'eqTickish'+ go (Tick n1 e1) (Tick n2 e2) = n1 == n2 && go e1 e2++ go (Lam b1 e1) (Lam b2 e2)+ = D env1 (varType b1) == D env2 (varType b2)+ && D env1 (varMultMaybe b1) == D env2 (varMultMaybe b2)+ && D (extendCME env1 b1) e1 == D (extendCME env2 b2) e2++ go (Let (NonRec v1 r1) e1) (Let (NonRec v2 r2) e2)+ = go r1 r2+ && D (extendCME env1 v1) e1 == D (extendCME env2 v2) e2++ go (Let (Rec ps1) e1) (Let (Rec ps2) e2)+ = equalLength ps1 ps2+ && D env1' rs1 == D env2' rs2+ && D env1' e1 == D env2' e2+ where+ (bs1,rs1) = unzip ps1+ (bs2,rs2) = unzip ps2+ env1' = extendCMEs env1 bs1+ env2' = extendCMEs env2 bs2++ go (Case e1 b1 t1 a1) (Case e2 b2 t2 a2)+ | null a1 -- See Note [Empty case alternatives]+ = null a2 && go e1 e2 && D env1 t1 == D env2 t2+ | otherwise+ = go e1 e2 && D (extendCME env1 b1) a1 == D (extendCME env2 b2) a2++ go _ _ = False++emptyE :: CoreMapX a+emptyE = CM { cm_var = emptyTM, cm_lit = emptyTM+ , cm_co = emptyTM, cm_type = emptyTM+ , cm_cast = emptyTM, cm_app = emptyTM+ , cm_lam = emptyTM, cm_letn = emptyTM+ , cm_letr = emptyTM, cm_case = emptyTM+ , cm_ecase = emptyTM, cm_tick = emptyTM }++instance TrieMap CoreMapX where+ type Key CoreMapX = DeBruijn CoreExpr+ emptyTM = emptyE+ lookupTM = lkE+ alterTM = xtE+ foldTM = fdE+ mapTM = mapE+ filterTM = ftE++--------------------------+mapE :: (a->b) -> CoreMapX a -> CoreMapX b+mapE f (CM { cm_var = cvar, cm_lit = clit+ , cm_co = cco, cm_type = ctype+ , cm_cast = ccast , cm_app = capp+ , cm_lam = clam, cm_letn = cletn+ , cm_letr = cletr, cm_case = ccase+ , cm_ecase = cecase, cm_tick = ctick })+ = CM { cm_var = mapTM f cvar, cm_lit = mapTM f clit+ , cm_co = mapTM f cco, cm_type = mapTM f ctype+ , cm_cast = mapTM (mapTM f) ccast, cm_app = mapTM (mapTM f) capp+ , cm_lam = mapTM (mapTM f) clam, cm_letn = mapTM (mapTM (mapTM f)) cletn+ , cm_letr = mapTM (mapTM (mapTM f)) cletr, cm_case = mapTM (mapTM f) ccase+ , cm_ecase = mapTM (mapTM f) cecase, cm_tick = mapTM (mapTM f) ctick }++ftE :: (a->Bool) -> CoreMapX a -> CoreMapX a+ftE f (CM { cm_var = cvar, cm_lit = clit+ , cm_co = cco, cm_type = ctype+ , cm_cast = ccast , cm_app = capp+ , cm_lam = clam, cm_letn = cletn+ , cm_letr = cletr, cm_case = ccase+ , cm_ecase = cecase, cm_tick = ctick })+ = CM { cm_var = filterTM f cvar, cm_lit = filterTM f clit+ , cm_co = filterTM f cco, cm_type = filterTM f ctype+ , cm_cast = mapTM (filterTM f) ccast, cm_app = mapTM (filterTM f) capp+ , cm_lam = mapTM (filterTM f) clam, cm_letn = mapTM (mapTM (filterTM f)) cletn+ , cm_letr = mapTM (mapTM (filterTM f)) cletr, cm_case = mapTM (filterTM f) ccase+ , cm_ecase = mapTM (filterTM f) cecase, cm_tick = mapTM (filterTM f) ctick }++--------------------------+lookupCoreMap :: CoreMap a -> CoreExpr -> Maybe a+lookupCoreMap cm e = lookupTM e cm++extendCoreMap :: CoreMap a -> CoreExpr -> a -> CoreMap a+extendCoreMap m e v = alterTM e (\_ -> Just v) m++foldCoreMap :: (a -> b -> b) -> b -> CoreMap a -> b+foldCoreMap k z m = foldTM k m z++emptyCoreMap :: CoreMap a+emptyCoreMap = emptyTM++instance Outputable a => Outputable (CoreMap a) where+ ppr m = text "CoreMap elts" <+> ppr (foldTM (:) m [])++-------------------------+fdE :: (a -> b -> b) -> CoreMapX a -> b -> b+fdE k m+ = foldTM k (cm_var m)+ . foldTM k (cm_lit m)+ . foldTM k (cm_co m)+ . foldTM k (cm_type m)+ . foldTM (foldTM k) (cm_cast m)+ . foldTM (foldTM k) (cm_tick m)+ . foldTM (foldTM k) (cm_app m)+ . foldTM (foldTM k) (cm_lam m)+ . foldTM (foldTM (foldTM k)) (cm_letn m)+ . foldTM (foldTM (foldTM k)) (cm_letr m)+ . foldTM (foldTM k) (cm_case m)+ . foldTM (foldTM k) (cm_ecase m)++-- lkE: lookup in trie for expressions+lkE :: DeBruijn CoreExpr -> CoreMapX a -> Maybe a+lkE (D env expr) cm = go expr cm+ where+ go (Var v) = cm_var >.> lkVar env v+ go (Lit l) = cm_lit >.> lookupTM l+ go (Type t) = cm_type >.> lkG (D env t)+ go (Coercion c) = cm_co >.> lkG (D env c)+ go (Cast e c) = cm_cast >.> lkG (D env e) >=> lkG (D env c)+ go (Tick tickish e) = cm_tick >.> lkG (D env e) >=> lkTickish tickish+ go (App e1 e2) = cm_app >.> lkG (D env e2) >=> lkG (D env e1)+ go (Lam v e) = cm_lam >.> lkG (D (extendCME env v) e)+ >=> lkBndr env v+ go (Let (NonRec b r) e) = cm_letn >.> lkG (D env r)+ >=> lkG (D (extendCME env b) e) >=> lkBndr env b+ go (Let (Rec prs) e) = let (bndrs,rhss) = unzip prs+ env1 = extendCMEs env bndrs+ in cm_letr+ >.> lkList (lkG . D env1) rhss+ >=> lkG (D env1 e)+ >=> lkList (lkBndr env1) bndrs+ go (Case e b ty as) -- See Note [Empty case alternatives]+ | null as = cm_ecase >.> lkG (D env e) >=> lkG (D env ty)+ | otherwise = cm_case >.> lkG (D env e)+ >=> lkList (lkA (extendCME env b)) as++xtE :: DeBruijn CoreExpr -> XT a -> CoreMapX a -> CoreMapX a+xtE (D env (Var v)) f m = m { cm_var = cm_var m+ |> xtVar env v f }+xtE (D env (Type t)) f m = m { cm_type = cm_type m+ |> xtG (D env t) f }+xtE (D env (Coercion c)) f m = m { cm_co = cm_co m+ |> xtG (D env c) f }+xtE (D _ (Lit l)) f m = m { cm_lit = cm_lit m |> alterTM l f }+xtE (D env (Cast e c)) f m = m { cm_cast = cm_cast m |> xtG (D env e)+ |>> xtG (D env c) f }+xtE (D env (Tick t e)) f m = m { cm_tick = cm_tick m |> xtG (D env e)+ |>> xtTickish t f }+xtE (D env (App e1 e2)) f m = m { cm_app = cm_app m |> xtG (D env e2)+ |>> xtG (D env e1) f }+xtE (D env (Lam v e)) f m = m { cm_lam = cm_lam m+ |> xtG (D (extendCME env v) e)+ |>> xtBndr env v f }+xtE (D env (Let (NonRec b r) e)) f m = m { cm_letn = cm_letn m+ |> xtG (D (extendCME env b) e)+ |>> xtG (D env r)+ |>> xtBndr env b f }+xtE (D env (Let (Rec prs) e)) f m = m { cm_letr =+ let (bndrs,rhss) = unzip prs+ env1 = extendCMEs env bndrs+ in cm_letr m+ |> xtList (xtG . D env1) rhss+ |>> xtG (D env1 e)+ |>> xtList (xtBndr env1)+ bndrs f }+xtE (D env (Case e b ty as)) f m+ | null as = m { cm_ecase = cm_ecase m |> xtG (D env e)+ |>> xtG (D env ty) f }+ | otherwise = m { cm_case = cm_case m |> xtG (D env e)+ |>> let env1 = extendCME env b+ in xtList (xtA env1) as f }++-- TODO: this seems a bit dodgy, see 'eqTickish'+type TickishMap a = Map.Map (Tickish Id) a+lkTickish :: Tickish Id -> TickishMap a -> Maybe a+lkTickish = lookupTM++xtTickish :: Tickish Id -> XT a -> TickishMap a -> TickishMap a+xtTickish = alterTM++------------------------+data AltMap a -- A single alternative+ = AM { am_deflt :: CoreMapG a+ , am_data :: DNameEnv (CoreMapG a)+ , am_lit :: LiteralMap (CoreMapG a) }++instance TrieMap AltMap where+ type Key AltMap = CoreAlt+ emptyTM = AM { am_deflt = emptyTM+ , am_data = emptyDNameEnv+ , am_lit = emptyTM }+ lookupTM = lkA emptyCME+ alterTM = xtA emptyCME+ foldTM = fdA+ mapTM = mapA+ filterTM = ftA++instance Eq (DeBruijn CoreAlt) where+ D env1 a1 == D env2 a2 = go a1 a2 where+ go (DEFAULT, _, rhs1) (DEFAULT, _, rhs2)+ = D env1 rhs1 == D env2 rhs2+ go (LitAlt lit1, _, rhs1) (LitAlt lit2, _, rhs2)+ = lit1 == lit2 && D env1 rhs1 == D env2 rhs2+ go (DataAlt dc1, bs1, rhs1) (DataAlt dc2, bs2, rhs2)+ = dc1 == dc2 &&+ D (extendCMEs env1 bs1) rhs1 == D (extendCMEs env2 bs2) rhs2+ go _ _ = False++mapA :: (a->b) -> AltMap a -> AltMap b+mapA f (AM { am_deflt = adeflt, am_data = adata, am_lit = alit })+ = AM { am_deflt = mapTM f adeflt+ , am_data = mapTM (mapTM f) adata+ , am_lit = mapTM (mapTM f) alit }++ftA :: (a->Bool) -> AltMap a -> AltMap a+ftA f (AM { am_deflt = adeflt, am_data = adata, am_lit = alit })+ = AM { am_deflt = filterTM f adeflt+ , am_data = mapTM (filterTM f) adata+ , am_lit = mapTM (filterTM f) alit }++lkA :: CmEnv -> CoreAlt -> AltMap a -> Maybe a+lkA env (DEFAULT, _, rhs) = am_deflt >.> lkG (D env rhs)+lkA env (LitAlt lit, _, rhs) = am_lit >.> lookupTM lit >=> lkG (D env rhs)+lkA env (DataAlt dc, bs, rhs) = am_data >.> lkDNamed dc+ >=> lkG (D (extendCMEs env bs) rhs)++xtA :: CmEnv -> CoreAlt -> XT a -> AltMap a -> AltMap a+xtA env (DEFAULT, _, rhs) f m =+ m { am_deflt = am_deflt m |> xtG (D env rhs) f }+xtA env (LitAlt l, _, rhs) f m =+ m { am_lit = am_lit m |> alterTM l |>> xtG (D env rhs) f }+xtA env (DataAlt d, bs, rhs) f m =+ m { am_data = am_data m |> xtDNamed d+ |>> xtG (D (extendCMEs env bs) rhs) f }++fdA :: (a -> b -> b) -> AltMap a -> b -> b+fdA k m = foldTM k (am_deflt m)+ . foldTM (foldTM k) (am_data m)+ . foldTM (foldTM k) (am_lit m)
compiler/GHC/Core/Opt/CSE.hs view
@@ -30,7 +30,7 @@ import GHC.Core import GHC.Utils.Outputable import GHC.Types.Basic-import GHC.Core.Map+import GHC.Core.Map.Expr import GHC.Utils.Misc ( filterOut, equalLength, debugIsOn ) import GHC.Utils.Panic import Data.List ( mapAccumL )
compiler/GHC/Core/Opt/CprAnal.hs view
@@ -322,7 +322,7 @@ not_strict = not (isStrUsedDmd (idDemandInfo id)) -- See Note [CPR for sum types] (_, ret_ty) = splitPiTys (idType id)- not_a_prod = isNothing (deepSplitProductType_maybe (ae_fam_envs env) ret_ty)+ not_a_prod = isNothing (splitArgType_maybe (ae_fam_envs env) ret_ty) returns_sum = not (isTopLevel top_lvl) && not_a_prod isDataStructure :: Id -> CoreExpr -> Bool@@ -425,7 +425,7 @@ extendSigEnvForDemand :: AnalEnv -> Id -> Demand -> AnalEnv extendSigEnvForDemand env id dmd | isId id- , Just (_, DataConAppContext { dcac_dc = dc })+ , Just (_, DataConPatContext { dcpc_dc = dc }) <- wantToUnbox (ae_fam_envs env) has_inlineable_prag (idType id) dmd = extendSigEnv env id (CprSig (conCprType (dataConTag dc))) | otherwise@@ -446,14 +446,12 @@ ids_w_strs = filter isId bndrs `zip` dataConRepStrictness dc - tycon = dataConTyCon dc- is_product = isJust (isDataProductTyCon_maybe tycon)- is_sum = isJust (isDataSumTyCon_maybe tycon)+ is_algebraic = isJust (tyConAlgDataCons_maybe (dataConTyCon dc))+ no_exs = null (dataConExTyCoVars dc) case_bndr_ty- | is_product || is_sum = conCprType (dataConTag dc)- -- Any of the constructors had existentials. This is a little too- -- conservative (after all, we only care about the particular data con),- -- but there is no easy way to write is_sum and this won't happen much.+ | is_algebraic, no_exs = conCprType (dataConTag dc)+ -- The tycon wasn't algebraic or the datacon had existentials.+ -- See Note [Which types are unboxed?] for why no existentials. | otherwise = topCprType -- We could have much deeper CPR info here with Nested CPR, which could
compiler/GHC/Core/Opt/DmdAnal.hs view
@@ -34,9 +34,10 @@ import GHC.Core.Utils import GHC.Core.TyCon import GHC.Core.Type-import GHC.Core.FVs ( exprFreeIds, ruleRhsFreeIds )+import GHC.Core.FVs ( rulesRhsFreeIds, bndrRuleAndUnfoldingIds ) import GHC.Core.Coercion ( Coercion, coVarsOfCo ) import GHC.Core.FamInstEnv+import GHC.Core.Opt.Arity ( typeArity ) import GHC.Utils.Misc import GHC.Utils.Panic import GHC.Data.Maybe ( isJust )@@ -64,29 +65,56 @@ -- -- Note: use `seqBinds` on the result to avoid leaks due to lazyness (cf Note -- [Stamp out space leaks in demand analysis])-dmdAnalProgram :: DmdAnalOpts -> FamInstEnvs -> CoreProgram -> CoreProgram-dmdAnalProgram opts fam_envs binds = binds_plus_dmds- where- env = emptyAnalEnv opts fam_envs- binds_plus_dmds = snd $ mapAccumL dmdAnalTopBind env binds---- Analyse a (group of) top-level binding(s)-dmdAnalTopBind :: AnalEnv- -> CoreBind- -> (AnalEnv, CoreBind)-dmdAnalTopBind env (NonRec id rhs)- = ( extendAnalEnv TopLevel env id sig- , NonRec (setIdStrictness id sig) rhs')+dmdAnalProgram :: DmdAnalOpts -> FamInstEnvs -> [CoreRule] -> CoreProgram -> CoreProgram+dmdAnalProgram opts fam_envs rules binds+ = snd $ go (emptyAnalEnv opts fam_envs) binds where- ( _, sig, rhs') = dmdAnalRhsLetDown Nothing env topSubDmd id rhs+ -- See Note [Analysing top-level bindings]+ -- and Note [Why care for top-level demand annotations?]+ go _ [] = (nopDmdType, [])+ go env (b:bs) = cons_up $ dmdAnalBind TopLevel env topSubDmd b anal_body+ where+ anal_body env'+ | (body_ty, bs') <- go env' bs+ = (add_exported_uses env' body_ty (bindersOf b), bs') -dmdAnalTopBind env (Rec pairs)- = (env', Rec pairs')- where- (env', _, pairs') = dmdFix TopLevel env topSubDmd pairs- -- We get two iterations automatically- -- c.f. the NonRec case above+ cons_up :: (a, b, [b]) -> (a, [b])+ cons_up (dmd_ty, b', bs') = (dmd_ty, b':bs') + 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@+ -- 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+ add_exported_use env dmd_ty id+ | isExportedId id || elemVarSet id rule_fvs+ -- See Note [Absence analysis for stable unfoldings and RULES]+ = dmd_ty `plusDmdType` fst (dmdAnalStar env topDmd (Var id))+ | otherwise+ = dmd_ty++ rule_fvs :: IdSet+ rule_fvs = rulesRhsFreeIds rules++-- | We attach useful (e.g. not 'topDmd') 'idDemandInfo' to top-level bindings+-- that satisfy this function.+--+-- Basically, we want to know how top-level *functions* are *used*+-- (e.g. called). The information will always be lazy.+-- Any other top-level bindings are boring.+--+-- See also Note [Why care for top-level demand annotations?].+isInterestingTopLevelFn :: Id -> Bool+-- SG tried to set this to True and got a +2% ghc/alloc regression in T5642+-- (which is dominated by the Simplifier) at no gain in analysis precision.+-- If there was a gain, that regression might be acceptable.+-- Plus, we could use LetUp for thunks and share some code with local let+-- bindings.+isInterestingTopLevelFn id =+ typeArity (idType id) `lengthExceeds` 0+ {- Note [Stamp out space leaks in demand analysis] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The demand analysis pass outputs a new copy of the Core program in@@ -105,16 +133,187 @@ unforced thunks in demand or strictness information; and it is the most memory-intensive part of the compilation process, so this added seqBinds makes a big difference in peak memory usage.--} +Note [Analysing top-level bindings]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider a CoreProgram like+ e1 = ...+ n1 = ...+ e2 = \a b -> ... fst (n1 a b) ...+ n2 = \c d -> ... snd (e2 c d) ...+ ...+where e* are exported, but n* are not.+Intuitively, we can see that @n1@ is only ever called with two arguments+and in every call site, the first component of the result of the call+is evaluated. Thus, we'd like it to have idDemandInfo @UCU(C1(P(SU,A))@.+NB: We may *not* give e2 a similar annotation, because it is exported and+external callers might use it in arbitrary ways, expressed by 'topDmd'.+This can then be exploited by Nested CPR and eta-expansion,+see Note [Why care for top-level demand annotations?]. +How do we get this result? Answer: By analysing the program as if it was a let+expression of this form:+ let e1 = ... in+ let n1 = ... in+ let e2 = ... in+ let n2 = ... in+ (e1,e2, ...)+E.g. putting all bindings in nested lets and returning all exported binders in a tuple.+Of course, we will not actually build that CoreExpr! Instead we faithfully+simulate analysis of said expression by adding the free variable 'DmdEnv'+of @e*@'s strictness signatures to the 'DmdType' we get from analysing the+nested bindings.++And even then the above form blows up analysis performance in T10370:+If @e1@ uses many free variables, we'll unnecessarily carry their demands around+with us from the moment we analyse the pair to the moment we bubble back up to+the binding for @e1@. So instead we analyse as if we had+ let e1 = ... in+ (e1, let n1 = ... in+ ( let e2 = ... in+ (e2, let n2 = ... in+ ( ...))))+That is, a series of right-nested pairs, where the @fst@ are the exported+binders of the last enclosing let binding and @snd@ continues the nested+lets.++Variables occuring free in RULE RHSs are to be handled the same as exported Ids.+See also Note [Absence analysis for stable unfoldings and RULES].++Note [Why care for top-level demand annotations?]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Reading Note [Analysing top-level bindings], you might think that we go through+quite some trouble to get useful demands for top-level bindings. They can never+be strict, for example, so why bother?++First, we get to eta-expand top-level bindings that we weren't able to+eta-expand before without Call Arity. From T18894b:+ module T18894b (f) where+ eta :: Int -> Int -> Int+ eta x = if fst (expensive x) == 13 then \y -> ... else \y -> ...+ f m = ... eta m 2 ... eta 2 m ...+Since only @f@ is exported, we see all call sites of @eta@ and can eta-expand to+arity 2.++The call demands we get for some top-level bindings will also allow Nested CPR+to unbox deeper. From T18894:+ module T18894 (h) where+ g m n = (2 * m, 2 `div` n)+ {-# NOINLINE g #-}+ h :: Int -> Int+ h m = ... snd (g m 2) ... uncurry (+) (g 2 m) ...+Only @h@ is exported, hence we see that @g@ is always called in contexts were we+also force the division in the second component of the pair returned by @g@.+This allows Nested CPR to evalute the division eagerly and return an I# in its+position.+-}+ {- ************************************************************************ * * \subsection{The analyser itself} * * ************************************************************************+-} +-- | Analyse a binding group and its \"body\", e.g. where it is in scope.+--+-- It calls a function that knows how to analyse this \"body\" given+-- an 'AnalEnv' with updated demand signatures for the binding group+-- (reflecting their 'idStrictnessInfo') and expects to receive a+-- 'DmdType' in return, which it uses to annotate the binding group with their+-- 'idDemandInfo'.+dmdAnalBind+ :: TopLevelFlag+ -> AnalEnv+ -> SubDemand -- ^ Demand put on the "body"+ -- (important for join points)+ -> CoreBind+ -> (AnalEnv -> (DmdType, a)) -- ^ How to analyse the "body", e.g.+ -- where the binding is in scope+ -> (DmdType, CoreBind, a)+dmdAnalBind top_lvl env dmd bind anal_body = case bind of+ NonRec id rhs+ | useLetUp top_lvl id+ -> dmdAnalBindLetUp top_lvl env id rhs anal_body+ _ -> dmdAnalBindLetDown top_lvl env dmd bind anal_body++-- | Annotates uninteresting top level functions ('isInterestingTopLevelFn')+-- with 'topDmd', the rest with the given demand.+setBindIdDemandInfo :: TopLevelFlag -> Id -> Demand -> Id+setBindIdDemandInfo top_lvl id dmd = setIdDemandInfo id $ case top_lvl of+ TopLevel | not (isInterestingTopLevelFn id) -> topDmd+ _ -> dmd++-- | Let bindings can be processed in two ways:+-- Down (RHS before body) or Up (body before RHS).+-- This function handles the up variant.+--+-- It is very simple. For let x = rhs in body+-- * Demand-analyse 'body' in the current environment+-- * Find the demand, 'rhs_dmd' placed on 'x' by 'body'+-- * Demand-analyse 'rhs' in 'rhs_dmd'+--+-- This is used for a non-recursive local let without manifest lambdas (see+-- 'useLetUp').+--+-- This is the LetUp rule in the paper “Higher-Order Cardinality Analysis”.+dmdAnalBindLetUp :: TopLevelFlag -> AnalEnv -> Id -> CoreExpr -> (AnalEnv -> (DmdType, a)) -> (DmdType, CoreBind, a)+dmdAnalBindLetUp top_lvl env id rhs anal_body = (final_ty, NonRec id' rhs', body')+ where+ (body_ty, body') = anal_body env+ (body_ty', id_dmd) = findBndrDmd env notArgOfDfun body_ty id+ id' = setBindIdDemandInfo top_lvl id id_dmd+ (rhs_ty, rhs') = dmdAnalStar env (dmdTransformThunkDmd rhs id_dmd) rhs++ -- See Note [Absence analysis for stable unfoldings and RULES]+ rule_fvs = bndrRuleAndUnfoldingIds id+ final_ty = body_ty' `plusDmdType` rhs_ty `keepAliveDmdType` rule_fvs++-- | Let bindings can be processed in two ways:+-- Down (RHS before body) or Up (body before RHS).+-- This function handles the down variant.+--+-- It computes a demand signature (by means of 'dmdAnalRhsSig') and uses+-- that at call sites in the body.+--+-- It is used for toplevel definitions, recursive definitions and local+-- non-recursive definitions that have manifest lambdas (cf. 'useLetUp').+-- Local non-recursive definitions without a lambda are handled with LetUp.+--+-- This is the LetDown rule in the paper “Higher-Order Cardinality Analysis”.+dmdAnalBindLetDown :: TopLevelFlag -> AnalEnv -> SubDemand -> CoreBind -> (AnalEnv -> (DmdType, a)) -> (DmdType, CoreBind, a)+dmdAnalBindLetDown top_lvl env dmd bind anal_body = case bind of+ NonRec id rhs+ | (env', lazy_fv, id1, rhs1) <-+ dmdAnalRhsSig top_lvl NonRecursive env dmd id rhs+ -> do_rest env' lazy_fv [(id1, rhs1)] (uncurry NonRec . only)+ Rec pairs+ | (env', lazy_fv, pairs') <- dmdFix top_lvl env dmd pairs+ -> do_rest env' lazy_fv pairs' Rec+ where+ do_rest env' lazy_fv pairs1 build_bind = (final_ty, build_bind pairs2, body')+ where+ (body_ty, body') = anal_body env'+ -- see Note [Lazy and unleashable free variables]+ dmd_ty = addLazyFVs body_ty lazy_fv+ (!final_ty, id_dmds) = findBndrsDmds env' dmd_ty (map fst pairs1)+ pairs2 = zipWith do_one pairs1 id_dmds+ do_one (id', rhs') dmd = (setBindIdDemandInfo top_lvl id' dmd, rhs')+ -- If the actual demand is better than the vanilla call+ -- demand, you might think that we might do better to re-analyse+ -- the RHS with the stronger demand.+ -- But (a) That seldom happens, because it means that *every* path in+ -- the body of the let has to use that stronger demand+ -- (b) It often happens temporarily in when fixpointing, because+ -- the recursive function at first seems to place a massive demand.+ -- But we don't want to go to extra work when the function will+ -- probably iterate to something less demanding.+ -- In practice, all the times the actual demand on id2 is more than+ -- the vanilla call demand seem to be due to (b). So we don't+ -- bother to re-analyse the RHS.++{- Note [Ensure demand is strict] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It's important not to analyse e with a lazy demand because@@ -194,7 +393,7 @@ -- Crucially, coercions /are/ handled here, because they are -- value arguments (#10288) let- call_dmd = mkCallDmd dmd+ call_dmd = mkCalledOnceDmd dmd (fun_ty, fun') = dmdAnal env call_dmd fun (arg_dmd, res_ty) = splitDmdTy fun_ty (arg_ty, arg') = dmdAnalStar env (dmdTransformThunkDmd arg arg_dmd) arg@@ -227,8 +426,8 @@ dmdAnal' env dmd (Case scrut case_bndr ty [(alt, bndrs, rhs)]) -- Only one alternative.- -- If it's a DataAlt, it should be a product constructor.- | is_non_sum_alt alt+ -- If it's a DataAlt, it should be the only constructor of the type.+ | is_single_data_alt alt = let (rhs_ty, rhs') = dmdAnal env dmd rhs (alt_ty1, dmds) = findBndrsDmds env rhs_ty bndrs@@ -267,8 +466,8 @@ -- , text "res_ty" <+> ppr res_ty ]) $ (res_ty, Case scrut' case_bndr' ty [(alt, bndrs', rhs')]) where- is_non_sum_alt (DataAlt dc) = isJust $ isDataProductTyCon_maybe $ dataConTyCon dc- is_non_sum_alt _ = True+ is_single_data_alt (DataAlt dc) = isJust $ tyConSingleAlgDataCon_maybe $ dataConTyCon dc+ is_single_data_alt _ = True dmdAnal' env dmd (Case scrut case_bndr ty alts) = let -- Case expression with multiple alternatives@@ -295,60 +494,11 @@ -- , text "res_ty" <+> ppr res_ty ]) $ (res_ty, Case scrut' case_bndr' ty alts') --- Let bindings can be processed in two ways:--- Down (RHS before body) or Up (body before RHS).--- The following case handle the up variant.------ It is very simple. For let x = rhs in body--- * Demand-analyse 'body' in the current environment--- * Find the demand, 'rhs_dmd' placed on 'x' by 'body'--- * Demand-analyse 'rhs' in 'rhs_dmd'------ This is used for a non-recursive local let without manifest lambdas.--- This is the LetUp rule in the paper “Higher-Order Cardinality Analysis”.-dmdAnal' env dmd (Let (NonRec id rhs) body)- | useLetUp id- = (final_ty, Let (NonRec id' rhs') body')- where- (body_ty, body') = dmdAnal env dmd body- (body_ty', id_dmd) = findBndrDmd env notArgOfDfun body_ty id- id' = setIdDemandInfo id id_dmd-- (rhs_ty, rhs') = dmdAnalStar env (dmdTransformThunkDmd rhs id_dmd) rhs- final_ty = body_ty' `plusDmdType` rhs_ty--dmdAnal' env dmd (Let (NonRec id rhs) body)- = (body_ty2, Let (NonRec id2 rhs') body')+dmdAnal' env dmd (Let bind body)+ = (final_ty, Let bind' body') where- (lazy_fv, sig, rhs') = dmdAnalRhsLetDown Nothing env dmd id rhs- id1 = setIdStrictness id sig- env1 = extendAnalEnv NotTopLevel env id sig- (body_ty, body') = dmdAnal env1 dmd body- (body_ty1, id2) = annotateBndr env body_ty id1- body_ty2 = addLazyFVs body_ty1 lazy_fv -- see Note [Lazy and unleashable free variables]-- -- If the actual demand is better than the vanilla call- -- demand, you might think that we might do better to re-analyse- -- the RHS with the stronger demand.- -- But (a) That seldom happens, because it means that *every* path in- -- the body of the let has to use that stronger demand- -- (b) It often happens temporarily in when fixpointing, because- -- the recursive function at first seems to place a massive demand.- -- But we don't want to go to extra work when the function will- -- probably iterate to something less demanding.- -- In practice, all the times the actual demand on id2 is more than- -- the vanilla call demand seem to be due to (b). So we don't- -- bother to re-analyse the RHS.--dmdAnal' env dmd (Let (Rec pairs) body)- = let- (env', lazy_fv, pairs') = dmdFix NotTopLevel env dmd pairs- (body_ty, body') = dmdAnal env' dmd body- body_ty1 = deleteFVs body_ty (map fst pairs)- body_ty2 = addLazyFVs body_ty1 lazy_fv -- see Note [Lazy and unleashable free variables]- in- body_ty2 `seq`- (body_ty2, Let (Rec pairs') body')+ (final_ty, bind', body') = dmdAnalBind NotTopLevel env dmd bind go'+ go' env' = dmdAnal env' dmd body -- | A simple, syntactic analysis of whether an expression MAY throw a precise -- exception when evaluated. It's always sound to return 'True'.@@ -377,10 +527,11 @@ forcesRealWorld fam_envs ty | ty `eqType` realWorldStatePrimTy = True- | Just DataConAppContext{ dcac_dc = dc, dcac_arg_tys = field_tys }- <- deepSplitProductType_maybe fam_envs ty+ | Just DataConPatContext{ dcpc_dc = dc, dcpc_tc_args = tc_args }+ <- splitArgType_maybe fam_envs ty , isUnboxedTupleDataCon dc- = any (\(ty,_) -> scaledThing ty `eqType` realWorldStatePrimTy) field_tys+ , let field_tys = dataConInstArgTys dc tc_args+ = any (eqType realWorldStatePrimTy . scaledThing) field_tys | otherwise = False @@ -582,9 +733,17 @@ | Just (sig, top_lvl) <- lookupSigEnv env var , let fn_ty = dmdTransformSig sig dmd = -- pprTrace "dmdTransform:LetDown" (vcat [ppr var, ppr sig, ppr dmd, ppr fn_ty]) $- if isTopLevel top_lvl- then fn_ty -- Don't record demand on top-level things- else addVarDmd fn_ty var (C_11 :* dmd)+ case top_lvl of+ NotTopLevel -> addVarDmd fn_ty var (C_11 :* dmd)+ TopLevel+ | isInterestingTopLevelFn var+ -- Top-level things will be used multiple times or not at+ -- all anyway, hence the multDmd below: It means we don't+ -- have to track whether @var@ is used strictly or at most+ -- once, because ultimately it never will.+ -> addVarDmd fn_ty var (C_0N `multDmd` (C_11 :* dmd)) -- discard strictness+ | otherwise+ -> fn_ty -- don't bother tracking; just annotate with 'topDmd' later -- Everything else: -- * Local let binders for which we use LetUp (cf. 'useLetUp') -- * Lambda binders@@ -599,46 +758,46 @@ * * ********************************************************************* -} --- Let bindings can be processed in two ways:--- Down (RHS before body) or Up (body before RHS).--- dmdAnalRhsLetDown implements the Down variant:--- * assuming a demand of <L,U>+-- | @dmdAnalRhsSig@ analyses the given RHS to compute a demand signature+-- for the LetDown rule. It works as follows:+--+-- * assuming a demand of <U> -- * looking at the definition -- * determining a strictness signature ----- It is used for toplevel definition, recursive definitions and local--- non-recursive definitions that have manifest lambdas.--- Local non-recursive definitions without a lambda are handled with LetUp.------ This is the LetDown rule in the paper “Higher-Order Cardinality Analysis”.-dmdAnalRhsLetDown- :: Maybe [Id] -- Just bs <=> recursive, Nothing <=> non-recursive+-- Since it assumed a demand of <U>, the resulting signature is applicable at+-- any call site.+dmdAnalRhsSig+ :: TopLevelFlag+ -> RecFlag -> AnalEnv -> SubDemand -> Id -> CoreExpr- -> (DmdEnv, StrictSig, CoreExpr)+ -> (AnalEnv, DmdEnv, Id, CoreExpr) -- Process the RHS of the binding, add the strictness signature -- to the Id, and augment the environment with the signature as well. -- See Note [NOINLINE and strictness]-dmdAnalRhsLetDown rec_flag env let_dmd id rhs- = -- pprTrace "dmdAnalRhsLetDown" (ppr id $$ ppr let_dmd $$ ppr sig $$ ppr lazy_fv) $- (lazy_fv, sig, rhs')+dmdAnalRhsSig top_lvl rec_flag env let_dmd id rhs+ = -- pprTrace "dmdAnalRhsSig" (ppr id $$ ppr let_dmd $$ ppr sig $$ ppr lazy_fv) $+ (env', lazy_fv, id', rhs') where rhs_arity = idArity id+ -- See Note [Demand signatures are computed for a threshold demand based on idArity] rhs_dmd -- 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 | isJoinId id- = mkCallDmds rhs_arity let_dmd+ = mkCalledOnceDmds rhs_arity let_dmd | otherwise- -- NB: rhs_arity- -- See Note [Demand signatures are computed for a threshold demand based on idArity]- = mkRhsDmd env rhs_arity rhs+ = mkCalledOnceDmds rhs_arity topSubDmd (rhs_dmd_ty, rhs') = dmdAnal env rhs_dmd rhs DmdType rhs_fv rhs_dmds rhs_div = rhs_dmd_ty sig = mkStrictSigForArity rhs_arity (DmdType sig_fv rhs_dmds rhs_div) + id' = id `setIdStrictness` sig+ env' = extendAnalEnv top_lvl env id' sig+ -- See Note [Aggregated demand for cardinality] -- FIXME: That Note doesn't explain the following lines at all. The reason -- is really much different: When we have a recursive function, we'd@@ -651,31 +810,15 @@ -- we'd have to do an additional iteration. reuseEnv makes sure that -- we never get used-once info for FVs of recursive functions. rhs_fv1 = case rec_flag of- Just bs -> reuseEnv (delVarEnvList rhs_fv bs)- Nothing -> rhs_fv+ Recursive -> reuseEnv rhs_fv+ NonRecursive -> rhs_fv - rhs_fv2 = rhs_fv1 `keepAliveDmdEnv` extra_fvs- -- Find the RHS free vars of the unfoldings and RULES -- See Note [Absence analysis for stable unfoldings and RULES]- extra_fvs = foldr (unionVarSet . ruleRhsFreeIds) unf_fvs $- idCoreRules id+ rhs_fv2 = rhs_fv1 `keepAliveDmdEnv` bndrRuleAndUnfoldingIds id -- See Note [Lazy and unleashable free variables] (lazy_fv, sig_fv) = partitionVarEnv isWeakDmd rhs_fv2 - unf = realIdUnfolding id- unf_fvs | isStableUnfolding unf- , Just unf_body <- maybeUnfoldingTemplate unf- = exprFreeIds unf_body- | otherwise = emptyVarSet---- | @mkRhsDmd env rhs_arity rhs@ creates a 'SubDemand' for--- unleashing on the given function's @rhs@, by creating--- a call demand of @rhs_arity@--- See Historical Note [Product demands for function body]-mkRhsDmd :: AnalEnv -> Arity -> CoreExpr -> SubDemand-mkRhsDmd _env rhs_arity _rhs = mkCallDmds rhs_arity topSubDmd- -- | 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).@@ -720,8 +863,8 @@ -- * For a more convincing example with join points, see Note [Demand analysis -- for join points]. ---useLetUp :: Var -> Bool-useLetUp f = idArity f == 0 && not (isJoinId f)+useLetUp :: TopLevelFlag -> Var -> Bool+useLetUp top_lvl f = isNotTopLevel top_lvl && idArity f == 0 && not (isJoinId f) {- Note [Demand analysis for join points] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -939,8 +1082,6 @@ dmdFix top_lvl env let_dmd orig_pairs = loop 1 initial_pairs where- bndrs = map fst orig_pairs- -- See Note [Initialising strictness] initial_pairs | ae_virgin env = [(setIdStrictness id botSig, rhs) | (id, rhs) <- orig_pairs ] | otherwise = orig_pairs@@ -990,10 +1131,8 @@ = -- pprTrace "my_downRhs" (ppr id $$ ppr (idStrictness id) $$ ppr sig) $ ((env', lazy_fv'), (id', rhs')) where- (lazy_fv1, sig, rhs') = dmdAnalRhsLetDown (Just bndrs) env let_dmd id rhs- lazy_fv' = plusVarEnv_C plusDmd lazy_fv lazy_fv1- env' = extendAnalEnv top_lvl env id sig- id' = setIdStrictness id sig+ (env', lazy_fv1, id', rhs') = dmdAnalRhsSig top_lvl Recursive env let_dmd id rhs+ lazy_fv' = plusVarEnv_C plusDmd lazy_fv lazy_fv1 zapIdStrictness :: [(Id, CoreExpr)] -> [(Id, CoreExpr)] zapIdStrictness pairs = [(setIdStrictness id nopSig, rhs) | (id, rhs) <- pairs ]@@ -1090,7 +1229,7 @@ -- demand with the bottom coming up from 'error' -- -- I got a loop in the fixpointer without this, due to an interaction- -- with the lazy_fv filtering in dmdAnalRhsLetDown. Roughly, it was+ -- with the lazy_fv filtering in dmdAnalRhsSig. Roughly, it was -- letrec f n x -- = letrec g y = x `fatbar` -- letrec h z = z + ...g...@@ -1155,10 +1294,6 @@ main_ty = addDemand dmd dmd_ty' (dmd_ty', dmd) = findBndrDmd env arg_of_dfun dmd_ty id--deleteFVs :: DmdType -> [Var] -> DmdType-deleteFVs (DmdType fvs dmds res) bndrs- = DmdType (delVarEnvList fvs bndrs) dmds res {- Note [NOINLINE and strictness]
compiler/GHC/Core/Opt/Pipeline.hs view
@@ -66,6 +66,7 @@ import GHC.Types.Id import GHC.Types.Id.Info import GHC.Types.Basic+import GHC.Types.Demand ( zapDmdEnvSig ) import GHC.Types.Var.Set import GHC.Types.Var.Env import GHC.Types.Unique.Supply ( UniqSupply, mkSplitUniqSupply, splitUniqSupply )@@ -109,10 +110,7 @@ dflags = hsc_dflags hsc_env home_pkg_rules = hptRules hsc_env (dep_mods deps) hpt_rule_base = mkRuleBase home_pkg_rules- print_unqual = mkPrintUnqualified- (unitState dflags)- (hsc_home_unit hsc_env)- rdr_env+ print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) rdr_env -- mod: get the module out of the current HscEnv so we can retrieve it from the monad. -- This is very convienent for the users of the monad (e.g. plugins do not have to -- consume the ModGuts to find the module) but somewhat ugly because mg_module may@@ -499,7 +497,7 @@ doPass exitifyProgram doCorePass CoreDoDemand = {-# SCC "DmdAnal" #-}- doPassDFM dmdAnal+ doPassDFRM dmdAnal doCorePass CoreDoCpr = {-# SCC "CprAnal" #-} doPassDFM cprAnalProgram@@ -582,6 +580,13 @@ let fam_envs = (p_fam_env, mg_fam_inst_env guts) doPassM (liftIO . do_pass dflags fam_envs) guts +doPassDFRM :: (DynFlags -> FamInstEnvs -> [CoreRule] -> CoreProgram -> IO CoreProgram) -> ModGuts -> CoreM ModGuts+doPassDFRM do_pass guts = do+ dflags <- getDynFlags+ p_fam_env <- getPackageFamInstEnv+ let fam_envs = (p_fam_env, mg_fam_inst_env guts)+ doPassM (liftIO . do_pass dflags fam_envs (mg_rules guts)) guts+ doPassDFU :: (DynFlags -> FamInstEnvs -> UniqSupply -> CoreProgram -> CoreProgram) -> ModGuts -> CoreM ModGuts doPassDFU do_pass guts = do dflags <- getDynFlags@@ -714,7 +719,7 @@ } where dflags = hsc_dflags hsc_env- print_unqual = mkPrintUnqualified (unitState dflags) (hsc_home_unit hsc_env) rdr_env+ print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) rdr_env simpl_env = mkSimplEnv mode active_rule = activeRule mode active_unf = activeUnfolding mode@@ -1095,13 +1100,13 @@ -dmdAnal :: DynFlags -> FamInstEnvs -> CoreProgram -> IO CoreProgram-dmdAnal dflags fam_envs binds = do+dmdAnal :: DynFlags -> FamInstEnvs -> [CoreRule] -> CoreProgram -> IO CoreProgram+dmdAnal dflags fam_envs rules binds = do let opts = DmdAnalOpts { dmd_strict_dicts = gopt Opt_DictsStrict dflags }- binds_plus_dmds = dmdAnalProgram opts fam_envs binds+ binds_plus_dmds = dmdAnalProgram opts fam_envs rules binds Err.dumpIfSet_dyn dflags Opt_D_dump_str_signatures "Strictness signatures" FormatText $- dumpIdInfoOfProgram (ppr . strictnessInfo) binds_plus_dmds+ dumpIdInfoOfProgram (ppr . zapDmdEnvSig . strictnessInfo) binds_plus_dmds -- See Note [Stamp out space leaks in demand analysis] in GHC.Core.Opt.DmdAnal seqBinds binds_plus_dmds `seq` return binds_plus_dmds
compiler/GHC/Core/Opt/Simplify.hs view
@@ -2182,7 +2182,8 @@ [ text "Rule:" <+> ftext (ruleName rule) , text "Module:" <+> printRuleModule rule , text "Before:" <+> hang (ppr fn) 2 (sep (map ppr args))- , text "After: " <+> pprCoreExpr rule_rhs+ , text "After: " <+> hang (pprCoreExpr rule_rhs) 2+ (sep $ map ppr $ drop (ruleArity rule) args) , text "Cont: " <+> ppr call_cont ] | dopt Opt_D_dump_rule_firings dflags
compiler/GHC/Core/Opt/Simplify/Env.hs view
@@ -598,11 +598,10 @@ mkRecFloats :: SimplFloats -> SimplFloats -- Flattens the floats into a single Rec group, -- They must either all be lifted LetFloats or all JoinFloats-mkRecFloats floats@(SimplFloats { sfLetFloats = LetFloats bs ff+mkRecFloats floats@(SimplFloats { sfLetFloats = LetFloats bs _ff , sfJoinFloats = jbs , sfInScope = in_scope })- = ASSERT2( case ff of { FltLifted -> True; _ -> False }, ppr (fromOL bs) )- ASSERT2( isNilOL bs || isNilOL jbs, ppr floats )+ = ASSERT2( isNilOL bs || isNilOL jbs, ppr floats ) SimplFloats { sfLetFloats = floats' , sfJoinFloats = jfloats' , sfInScope = in_scope }
compiler/GHC/Core/Opt/WorkWrap.hs view
@@ -484,7 +484,7 @@ | is_fun && is_eta_exp = splitFun dflags fam_envs new_fn_id fn_info wrap_dmds div cpr rhs - | is_thunk -- See Note [Thunk splitting]+ | isNonRec is_rec, is_thunk -- See Note [Thunk splitting] = splitThunk dflags fam_envs is_rec new_fn_id rhs | otherwise@@ -777,6 +777,10 @@ In fact, splitThunk uses the function argument w/w splitting function, so that if x's demand is deeper (say U(U(L,L),L)) then the splitting will go deeper too.++NB: For recursive thunks, the Simplifier is unable to float `x-rhs` out of+`x*`'s RHS, because `x*` occurs freely in `x-rhs`, and will just change it+back to the original definition, so we just split non-recursive thunks. -} -- See Note [Thunk splitting]
compiler/GHC/Core/Opt/WorkWrap/Utils.hs view
@@ -8,7 +8,7 @@ module GHC.Core.Opt.WorkWrap.Utils ( mkWwBodies, mkWWstr, mkWorkerArgs- , DataConAppContext(..), deepSplitProductType_maybe, wantToUnbox+ , DataConPatContext(..), splitArgType_maybe, wantToUnbox , findTypeShape , isWorkerSmallEnough )@@ -19,7 +19,8 @@ import GHC.Prelude import GHC.Core-import GHC.Core.Utils ( exprType, mkCast, mkDefaultCase, mkSingleAltCase )+import GHC.Core.Utils ( exprType, mkCast, mkDefaultCase, mkSingleAltCase+ , dataConRepFSInstPat ) import GHC.Types.Id import GHC.Types.Id.Info ( JoinArity ) import GHC.Core.DataCon@@ -43,9 +44,11 @@ import GHC.Core.TyCon.RecWalk import GHC.Types.Unique.Supply import GHC.Types.Unique+import GHC.Types.Name ( getOccFS ) import GHC.Data.Maybe import GHC.Utils.Misc import GHC.Utils.Outputable+import GHC.Utils.Panic import GHC.Driver.Session import GHC.Driver.Ppr import GHC.Data.FastString@@ -606,53 +609,53 @@ arg_ty = idType arg dmd = idDemandInfo arg -wantToUnbox :: FamInstEnvs -> Bool -> Type -> Demand -> Maybe ([Demand], DataConAppContext)+wantToUnbox :: FamInstEnvs -> Bool -> Type -> Demand -> Maybe ([Demand], DataConPatContext)+-- See Note [Which types are unboxed?] wantToUnbox fam_envs has_inlineable_prag ty dmd =- case deepSplitProductType_maybe fam_envs ty of- Just dcac@DataConAppContext{ dcac_arg_tys = con_arg_tys }+ case splitArgType_maybe fam_envs ty of+ Just dcpc@DataConPatContext{ dcpc_dc = dc } | isStrUsedDmd dmd+ , let arity = dataConRepArity dc -- See Note [Unpacking arguments with product and polymorphic demands]- , Just cs <- split_prod_dmd_arity dmd (length con_arg_tys)+ , Just cs <- split_prod_dmd_arity dmd arity -- See Note [Do not unpack class dictionaries] , not (has_inlineable_prag && isClassPred ty) -- See Note [mkWWstr and unsafeCoerce]- , cs `equalLength` con_arg_tys- -> Just (cs, dcac)+ , cs `lengthIs` arity+ -> Just (cs, dcpc) _ -> Nothing where- split_prod_dmd_arity dmd arty+ split_prod_dmd_arity dmd arity -- For seqDmd, it should behave like <S(AAAA)>, for some -- suitable arity- | isSeqDmd dmd = Just (replicate arty absDmd)+ | isSeqDmd dmd = Just (replicate arity absDmd) | _ :* Prod ds <- dmd = Just ds | otherwise = Nothing unbox_one :: DynFlags -> FamInstEnvs -> Var -> [Demand]- -> DataConAppContext+ -> DataConPatContext -> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr) unbox_one dflags fam_envs arg cs- DataConAppContext { dcac_dc = data_con, dcac_tys = inst_tys- , dcac_arg_tys = inst_con_arg_tys- , dcac_co = co }- = do { (uniq1:uniqs) <- getUniquesM- ; let scale = scaleScaled (idMult arg)- scaled_inst_con_arg_tys = map (\(t,s) -> (scale t, s)) inst_con_arg_tys- -- See Note [Add demands for strict constructors]- cs' = addDataConStrictness data_con cs- unpk_args = zipWith3 mk_ww_arg uniqs scaled_inst_con_arg_tys cs'- unbox_fn = mkUnpackCase (Var arg) co (idMult arg) uniq1- data_con unpk_args- arg_no_unf = zapStableUnfolding arg- -- See Note [Zap unfolding when beta-reducing]- -- in GHC.Core.Opt.Simplify; and see #13890- rebox_fn = Let (NonRec arg_no_unf con_app)- con_app = mkConApp2 data_con inst_tys unpk_args `mkCast` mkSymCo co- ; (_, worker_args, wrap_fn, work_fn) <- mkWWstr dflags fam_envs False unpk_args- ; return (True, worker_args, unbox_fn . wrap_fn, work_fn . rebox_fn) }- -- Don't pass the arg, rebox instead- where- mk_ww_arg uniq ty sub_dmd = setIdDemandInfo (mk_ww_local uniq ty) sub_dmd+ DataConPatContext { dcpc_dc = dc, dcpc_tc_args = tc_args+ , dcpc_co = co }+ = do { (case_bndr_uniq:pat_bndrs_uniqs) <- getUniquesM+ ; let ex_name_fss = map getOccFS $ dataConExTyCoVars dc+ (ex_tvs', arg_ids) =+ dataConRepFSInstPat (ex_name_fss ++ repeat ww_prefix) pat_bndrs_uniqs (idMult arg) dc tc_args+ -- See Note [Add demands for strict constructors]+ cs' = addDataConStrictness dc cs+ arg_ids' = zipWithEqual "unbox_one" setIdDemandInfo arg_ids cs'+ unbox_fn = mkUnpackCase (Var arg) co (idMult arg) case_bndr_uniq+ dc (ex_tvs' ++ arg_ids')+ arg_no_unf = zapStableUnfolding arg+ -- See Note [Zap unfolding when beta-reducing]+ -- in GHC.Core.Opt.Simplify; and see #13890+ rebox_fn = Let (NonRec arg_no_unf con_app)+ con_app = mkConApp2 dc tc_args (ex_tvs' ++ arg_ids') `mkCast` mkSymCo co+ ; (_, worker_args, wrap_fn, work_fn) <- mkWWstr dflags fam_envs False (ex_tvs' ++ arg_ids')+ ; return (True, worker_args, unbox_fn . wrap_fn, work_fn . rebox_fn) }+ -- Don't pass the arg, rebox instead ---------------------- nop_fn :: CoreExpr -> CoreExpr@@ -932,74 +935,68 @@ Historical note: #14955 describes how I got this fix wrong the first time. -} --- | Context for a 'DataCon' application with a hole for every field, including--- surrounding coercions.--- The result of 'deepSplitProductType_maybe' and 'deepSplitCprType_maybe'.------ Example:------ > DataConAppContext Just [Int] [(Lazy, Int)] (co :: Maybe Int ~ First Int)------ represents------ > Just @Int (_1 :: Int) |> co :: First Int+-- | The result of 'splitArgType_maybe' and 'splitResultType_maybe'. ----- where _1 is a hole for the first argument. The number of arguments is--- determined by the length of @arg_tys@.-data DataConAppContext- = DataConAppContext- { dcac_dc :: !DataCon- , dcac_tys :: ![Type]- , dcac_arg_tys :: ![(Scaled Type, StrictnessMark)]- , dcac_co :: !Coercion+-- Both splits+-- * Take a type `ty`+-- * Succeed with (DataConPatContext dc tys co)+-- iff co :: T tys ~ ty+-- and `dc` is the appropriate DataCon of `T`+-- and `T` is suitable for the kind of split+-- (differs for strictness and CPR, see Note [Which types are unboxed?])+data DataConPatContext+ = DataConPatContext+ { dcpc_dc :: !DataCon+ , dcpc_tc_args :: ![Type]+ , dcpc_co :: !Coercion } -deepSplitProductType_maybe :: FamInstEnvs -> Type -> Maybe DataConAppContext--- If deepSplitProductType_maybe ty = Just (dc, tys, arg_tys, co)--- then dc @ tys (args::arg_tys) :: rep_ty--- co :: ty ~ rep_ty--- Why do we return the strictness of the data-con arguments?--- Answer: see Note [Record evaluated-ness in worker/wrapper]-deepSplitProductType_maybe fam_envs ty+-- | If @splitArgType_maybe ty = Just (dc, tys, co)@+-- then @dc \@tys \@_ex_tys (_args::_arg_tys) :: tc tys@+-- and @co :: ty ~ tc tys@+-- where underscore prefixes are holes, e.g. yet unspecified.+--+-- See Note [Which types are unboxed?].+splitArgType_maybe :: FamInstEnvs -> Type -> Maybe DataConPatContext+splitArgType_maybe fam_envs ty | let (co, ty1) = topNormaliseType_maybe fam_envs ty `orElse` (mkRepReflCo ty, ty) , Just (tc, tc_args) <- splitTyConApp_maybe ty1- , Just con <- isDataProductTyCon_maybe tc- , let arg_tys = dataConInstArgTys con tc_args- strict_marks = dataConRepStrictness con- = Just DataConAppContext { dcac_dc = con- , dcac_tys = tc_args- , dcac_arg_tys = zipEqual "dspt" arg_tys strict_marks- , dcac_co = co }-deepSplitProductType_maybe _ _ = Nothing+ , Just con <- tyConSingleAlgDataCon_maybe tc+ = Just DataConPatContext { dcpc_dc = con+ , dcpc_tc_args = tc_args+ , dcpc_co = co }+splitArgType_maybe _ _ = Nothing -deepSplitCprType_maybe- :: FamInstEnvs -> ConTag -> Type -> Maybe DataConAppContext--- If deepSplitCprType_maybe n ty = Just (dc, tys, arg_tys, co)--- then dc @ tys (args::arg_tys) :: rep_ty--- co :: ty ~ rep_ty--- Why do we return the strictness of the data-con arguments?--- Answer: see Note [Record evaluated-ness in worker/wrapper]-deepSplitCprType_maybe fam_envs con_tag ty+-- | If @splitResultType_maybe n ty = Just (dc, tys, co)@+-- then @dc \@tys \@_ex_tys (_args::_arg_tys) :: tc tys@+-- and @co :: ty ~ tc tys@+-- where underscore prefixes are holes, e.g. yet unspecified.+-- @dc@ is the @n@th data constructor of @tc@.+--+-- See Note [Which types are unboxed?].+splitResultType_maybe :: FamInstEnvs -> ConTag -> Type -> Maybe DataConPatContext+splitResultType_maybe fam_envs con_tag ty | let (co, ty1) = topNormaliseType_maybe fam_envs ty `orElse` (mkRepReflCo ty, ty) , Just (tc, tc_args) <- splitTyConApp_maybe ty1- , isDataTyCon tc+ , isDataTyCon tc -- NB: rules out unboxed sums and pairs! , let cons = tyConDataCons tc , cons `lengthAtLeast` con_tag -- This might not be true if we import the- -- type constructor via a .hs-bool file (#8743)+ -- type constructor via a .hs-boot file (#8743) , let con = cons `getNth` (con_tag - fIRST_TAG)- arg_tys = dataConInstArgTys con tc_args- strict_marks = dataConRepStrictness con- , all isLinear arg_tys+ , null (dataConExTyCoVars con) -- no existentials;+ -- See Note [Which types are unboxed?]+ -- and GHC.Core.Opt.CprAnal.extendEnvForDataAlt+ -- where we also check this.+ , all isLinear (dataConInstArgTys con tc_args) -- Deactivates CPR worker/wrapper splits on constructors with non-linear -- arguments, for the moment, because they require unboxed tuple with variable -- multiplicity fields.- = Just DataConAppContext { dcac_dc = con- , dcac_tys = tc_args- , dcac_arg_tys = zipEqual "dspt" arg_tys strict_marks- , dcac_co = co }-deepSplitCprType_maybe _ _ _ = Nothing+ = Just DataConPatContext { dcpc_dc = con+ , dcpc_tc_args = tc_args+ , dcpc_co = co }+splitResultType_maybe _ _ _ = Nothing isLinear :: Scaled a -> Bool isLinear (Scaled w _ ) =@@ -1035,13 +1032,16 @@ | Just (_, rhs, _) <- topReduceTyFamApp_maybe fam_envs tc tc_args = go rec_tc rhs - | Just con <- isDataProductTyCon_maybe tc+ | Just con <- tyConSingleAlgDataCon_maybe tc , Just rec_tc <- if isTupleTyCon tc then Just rec_tc else checkRecTc rec_tc tc -- We treat tuples specially because they can't cause loops. -- Maybe we should do so in checkRecTc.- = TsProd (map (go rec_tc . scaledThing) (dataConInstArgTys con tc_args))+ -- The use of 'dubiousDataConInstArgTys' is OK, since this+ -- function performs no substitution at all, hence the uniques+ -- don't matter.+ = TsProd (map (go rec_tc) (dubiousDataConInstArgTys con tc_args)) | Just (ty', _) <- instNewTyCon_maybe tc tc_args , Just rec_tc <- checkRecTc rec_tc tc@@ -1050,7 +1050,55 @@ | otherwise = TsUnk -{-+-- | Exactly 'dataConInstArgTys', but lacks the (ASSERT'ed) precondition that+-- the 'DataCon' may not have existentials. The lack of cloning the existentials+-- compared to 'dataConInstExAndArgVars' makes this function \"dubious\";+-- only use it where type variables aren't substituted for!+dubiousDataConInstArgTys :: DataCon -> [Type] -> [Type]+dubiousDataConInstArgTys dc tc_args = arg_tys+ where+ univ_tvs = dataConUnivTyVars dc+ ex_tvs = dataConExTyCoVars dc+ subst = extendTCvInScopeList (zipTvSubst univ_tvs tc_args) ex_tvs+ arg_tys = map (substTy subst . scaledThing) (dataConRepArgTys dc)++{- Note [Which types are unboxed?]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Worker/wrapper will unbox++ 1. A strict data type argument, that+ * is an algebraic data type (not a newtype)+ * has a single constructor (thus is a "product")+ * that may bind existentials+ We can transform+ > f (D @ex a b) = e+ to+ > $wf @ex a b = e+ via 'mkWWstr'.++ 2. The constructed result of a function, if+ * its type is an algebraic data type (not a newtype)+ * (might have multiple constructors, in contrast to (1))+ * the applied data constructor *does not* bind existentials+ We can transform+ > f x y = let ... in D a b+ to+ > $wf x y = let ... in (# a, b #)+ via 'mkWWcpr'.++ NB: We don't allow existentials for CPR W/W, because we don't have unboxed+ dependent tuples (yet?). Otherwise, we could transform+ > f x y = let ... in D @ex (a :: ..ex..) (b :: ..ex..)+ to+ > $wf x y = let ... in (# @ex, (a :: ..ex..), (b :: ..ex..) #)++The respective tests are in 'splitArgType_maybe' and+'splitResultType_maybe', respectively.++Note that the data constructor /can/ have evidence arguments: equality+constraints, type classes etc. So it can be GADT. These evidence+arguments are simply value arguments, and should not get in the way.+ ************************************************************************ * * \subsection{CPR stuff}@@ -1083,35 +1131,36 @@ | otherwise = case asConCpr cpr of Nothing -> return (False, id, id, body_ty) -- No CPR info- Just con_tag | Just dcac <- deepSplitCprType_maybe fam_envs con_tag body_ty- -> mkWWcpr_help dcac+ Just con_tag | Just dcpc <- splitResultType_maybe fam_envs con_tag body_ty+ -> mkWWcpr_help dcpc | otherwise -- See Note [non-algebraic or open body type warning] -> WARN( True, text "mkWWcpr: non-algebraic or open body type" <+> ppr body_ty ) return (False, id, id, body_ty) -mkWWcpr_help :: DataConAppContext+mkWWcpr_help :: DataConPatContext -> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Type) -mkWWcpr_help (DataConAppContext { dcac_dc = data_con, dcac_tys = inst_tys- , dcac_arg_tys = arg_tys, dcac_co = co })- | [arg1@(arg_ty1, _)] <- arg_tys- , isUnliftedType (scaledThing arg_ty1)- , isLinear arg_ty1+mkWWcpr_help (DataConPatContext { dcpc_dc = dc, dcpc_tc_args = tc_args+ , dcpc_co = co })+ | [arg_ty] <- dataConInstArgTys dc tc_args -- NB: No existentials!+ , [str_mark] <- dataConRepStrictness dc+ , isUnliftedType (scaledThing arg_ty)+ , isLinear arg_ty -- Special case when there is a single result of unlifted, linear, type -- -- Wrapper: case (..call worker..) of x -> C x -- Worker: case ( ..body.. ) of C x -> x = do { (work_uniq : arg_uniq : _) <- getUniquesM- ; let arg = mk_ww_local arg_uniq arg1- con_app = mkConApp2 data_con inst_tys [arg] `mkCast` mkSymCo co+ ; let arg_id = mk_ww_local arg_uniq str_mark arg_ty+ con_app = mkConApp2 dc tc_args [arg_id] `mkCast` mkSymCo co ; return ( True- , \ wkr_call -> mkDefaultCase wkr_call arg con_app- , \ body -> mkUnpackCase body co One work_uniq data_con [arg] (varToCoreExpr arg)+ , \ wkr_call -> mkDefaultCase wkr_call arg_id con_app+ , \ body -> mkUnpackCase body co One work_uniq dc [arg_id] (varToCoreExpr arg_id) -- varToCoreExpr important here: arg can be a coercion -- Lacking this caused #10658- , scaledThing arg_ty1 ) }+ , scaledThing arg_ty ) } | otherwise -- The general case -- Wrapper: case (..call worker..) of (# a, b #) -> C a b@@ -1123,18 +1172,22 @@ -- parametrised by the multiplicity of its fields. Specifically, in this -- instance, the multiplicity of the fields of (#,#) is chosen to be the -- same as those of C.- = do { (work_uniq : wild_uniq : uniqs) <- getUniquesM- ; let wrap_wild = mk_ww_local wild_uniq (linear ubx_tup_ty,MarkedStrict)- args = zipWith mk_ww_local uniqs arg_tys- ubx_tup_ty = exprType ubx_tup_app- ubx_tup_app = mkCoreUbxTup (map (scaledThing . fst) arg_tys) (map varToCoreExpr args)- con_app = mkConApp2 data_con inst_tys args `mkCast` mkSymCo co- tup_con = tupleDataCon Unboxed (length arg_tys)+ = do { (work_uniq : wild_uniq : pat_bndrs_uniqs) <- getUniquesM+ ; let case_mult = One -- see above+ (_exs, arg_ids) =+ dataConRepFSInstPat (repeat ww_prefix) pat_bndrs_uniqs case_mult dc tc_args+ wrap_wild = mk_ww_local wild_uniq MarkedStrict (Scaled case_mult ubx_tup_ty)+ ubx_tup_ty = exprType ubx_tup_app+ ubx_tup_app = mkCoreUbxTup (map idType arg_ids) (map varToCoreExpr arg_ids)+ con_app = mkConApp2 dc tc_args arg_ids `mkCast` mkSymCo co+ tup_con = tupleDataCon Unboxed (length arg_ids) + ; MASSERT( null _exs ) -- Should have been caught by splitResultType_maybe+ ; return (True , \ wkr_call -> mkSingleAltCase wkr_call wrap_wild- (DataAlt tup_con) args con_app- , \ body -> mkUnpackCase body co One work_uniq data_con args ubx_tup_app+ (DataAlt tup_con) arg_ids con_app+ , \ body -> mkUnpackCase body co case_mult work_uniq dc arg_ids ubx_tup_app , ubx_tup_ty ) } mkUnpackCase :: CoreExpr -> Coercion -> Mult -> Unique -> DataCon -> [Id] -> CoreExpr -> CoreExpr@@ -1149,7 +1202,7 @@ (DataAlt boxing_con) unpk_args body where casted_scrut = scrut `mkCast` co- bndr = mk_ww_local uniq (Scaled mult (exprType casted_scrut), MarkedStrict)+ bndr = mk_ww_local uniq MarkedStrict (Scaled mult (exprType casted_scrut)) -- An unpacking case can always be chosen linear, because the variables -- are always passed to a constructor. This limits the {-@@ -1275,10 +1328,14 @@ abs_rhs = mkAbsentErrorApp arg_ty msg msg = showSDoc (gopt_set dflags Opt_SuppressUniques)- (ppr arg <+> ppr (idType arg) <+> file_msg)+ (vcat+ [ text "Arg:" <+> ppr arg+ , text "Type:" <+> ppr arg_ty+ , file_msg+ ]) file_msg = case outputFile dflags of Nothing -> empty- Just f -> text "in output file " <+> quotes (text f)+ Just f -> text "In output file " <+> quotes (text f) -- We need to suppress uniques here because otherwise they'd -- end up in the generated code as strings. This is bad for -- determinism, because with different uniques the strings@@ -1287,10 +1344,13 @@ -- See also Note [Unique Determinism] in GHC.Types.Unique unlifted_rhs = mkTyApps (Lit rubbishLit) [arg_ty] -mk_ww_local :: Unique -> (Scaled Type, StrictnessMark) -> Id+ww_prefix :: FastString+ww_prefix = fsLit "ww"++mk_ww_local :: Unique -> StrictnessMark -> Scaled Type -> Id -- The StrictnessMark comes form the data constructor and says -- whether this field is strict -- See Note [Record evaluated-ness in worker/wrapper]-mk_ww_local uniq (Scaled w ty,str)+mk_ww_local uniq str (Scaled w ty) = setCaseBndrEvald str $- mkSysLocalOrCoVar (fsLit "ww") uniq w ty+ mkSysLocalOrCoVar ww_prefix uniq w ty
compiler/GHC/Core/Tidy.hs view
@@ -21,7 +21,7 @@ import GHC.Core.Seq ( seqUnfolding ) import GHC.Types.Id import GHC.Types.Id.Info-import GHC.Types.Demand ( zapUsageEnvSig )+import GHC.Types.Demand ( zapDmdEnvSig ) import GHC.Core.Type ( tidyType, tidyVarBndr ) import GHC.Core.Coercion ( tidyCo ) import GHC.Types.Var@@ -206,7 +206,7 @@ new_info = vanillaIdInfo `setOccInfo` occInfo old_info `setArityInfo` arityInfo old_info- `setStrictnessInfo` zapUsageEnvSig (strictnessInfo old_info)+ `setStrictnessInfo` zapDmdEnvSig (strictnessInfo old_info) `setDemandInfo` demandInfo old_info `setInlinePragInfo` inlinePragInfo old_info `setUnfoldingInfo` new_unf
compiler/GHC/CoreToStg/Prep.hs view
@@ -768,7 +768,10 @@ -> UniqSM (Floats, CpeRhs) cpe_app env (Var f) (CpeApp Type{} : CpeApp arg : args) depth | f `hasKey` lazyIdKey -- Replace (lazy a) with a, and+ -- See Note [lazyId magic] in GHC.Types.Id.Make || f `hasKey` noinlineIdKey -- Replace (noinline a) with a+ -- See Note [noinlineId magic] in GHC.Types.Id.Make+ -- Consider the code: -- -- lazy (f x) y
compiler/GHC/Driver/Backpack.hs view
@@ -56,10 +56,12 @@ import GHC.Utils.Error import GHC.Unit+import GHC.Unit.Env import GHC.Unit.External import GHC.Unit.State import GHC.Unit.Finder-import GHC.Unit.Module.ModSummary (showModMsg)+import GHC.Unit.Module.Graph+import GHC.Unit.Module.ModSummary import GHC.Unit.Home.ModInfo import GHC.Linker.Types@@ -69,6 +71,7 @@ import GHC.Data.Maybe import GHC.Data.StringBuffer import GHC.Data.FastString+import qualified GHC.Data.EnumSet as EnumSet import qualified GHC.Data.ShortText as ST import Data.List ( partition )@@ -81,6 +84,7 @@ import Data.IORef import Data.Map (Map) import qualified Data.Map as Map+import qualified Data.Set as Set -- | Entry point to compile a Backpack file. doBackpack :: [FilePath] -> Ghc ()@@ -103,8 +107,8 @@ POk _ pkgname_bkp -> do -- OK, so we have an LHsUnit PackageName, but we want an -- LHsUnit HsComponentId. So let's rename it.- let pkgstate = unitState dflags- let bkp = renameHsUnits pkgstate (bkpPackageNameMap pkgname_bkp) pkgname_bkp+ hsc_env <- getSession+ let bkp = renameHsUnits (hsc_units hsc_env) (bkpPackageNameMap pkgname_bkp) pkgname_bkp initBkpM src_filename bkp $ forM_ (zip [1..] bkp) $ \(i, lunit) -> do let comp_name = unLoc (hsunitName (unLoc lunit))@@ -170,62 +174,68 @@ -- Special case when package is definite , not (null insts) = sub_comp (key_base p) </> uid_str | otherwise = sub_comp (key_base p)- withTempSession (overHscDynFlags (\dflags ->- -- If we're type-checking an indefinite package, we want to- -- turn on interface writing. However, if the user also- -- explicitly passed in `-fno-code`, we DON'T want to write- -- interfaces unless the user also asked for `-fwrite-interface`.- -- See Note [-fno-code mode]- (case session_type of- -- Make sure to write interfaces when we are type-checking- -- indefinite packages.- TcSession | backend dflags /= NoBackend- -> flip gopt_set Opt_WriteInterface- | otherwise -> id- CompSession -> id- ExeSession -> id) $- dflags {- backend = case session_type of- TcSession -> NoBackend- _ -> backend dflags,- homeUnitInstantiations_ = insts,- -- if we don't have any instantiation, don't- -- fill `homeUnitInstanceOfId` as it makes no- -- sense (we're not instantiating anything)- homeUnitInstanceOf_ = if null insts then Nothing else Just (indefUnit cid),- homeUnitId_ =- case session_type of++ mk_temp_env hsc_env = hsc_env+ { hsc_dflags = mk_temp_dflags (hsc_units hsc_env) (hsc_dflags hsc_env)+ }+ mk_temp_dflags unit_state dflags = dflags+ { backend = case session_type of+ TcSession -> NoBackend+ _ -> backend dflags+ , homeUnitInstantiations_ = insts+ -- if we don't have any instantiation, don't+ -- fill `homeUnitInstanceOfId` as it makes no+ -- sense (we're not instantiating anything)+ , homeUnitInstanceOf_ = if null insts then Nothing else Just (indefUnit cid)+ , homeUnitId_ = case session_type of TcSession -> newUnitId cid Nothing -- No hash passed if no instances _ | null insts -> newUnitId cid Nothing- | otherwise -> newUnitId cid (Just (mkInstantiatedUnitHash cid insts)),- -- Setup all of the output directories according to our hierarchy- objectDir = Just (outdir objectDir),- hiDir = Just (outdir hiDir),- stubDir = Just (outdir stubDir),- -- Unset output-file for non exe builds- outputFile_ = if session_type == ExeSession- then outputFile_ dflags- else Nothing,- dynOutputFile_ = if session_type == ExeSession- then dynOutputFile_ dflags- else Nothing,- -- Clear the import path so we don't accidentally grab anything- importPaths = [],- -- Synthesized the flags- packageFlags = packageFlags dflags ++ map (\(uid0, rn) ->- let state = unitState dflags- uid = unwireUnit state (improveUnit state $ renameHoleUnit state (listToUFM insts) uid0)- in ExposePackage- (showSDoc dflags- (text "-unit-id" <+> ppr uid <+> ppr rn))- (UnitIdArg uid) rn) deps- } )) $ do- dflags <- getSessionDynFlags- -- pprTrace "flags" (ppr insts <> ppr deps) $ return ()- setSessionDynFlags dflags -- calls initUnits- do_this+ | otherwise -> newUnitId cid (Just (mkInstantiatedUnitHash cid insts)) ++ -- If we're type-checking an indefinite package, we want to+ -- turn on interface writing. However, if the user also+ -- explicitly passed in `-fno-code`, we DON'T want to write+ -- interfaces unless the user also asked for `-fwrite-interface`.+ -- See Note [-fno-code mode]+ , generalFlags = case session_type of+ -- Make sure to write interfaces when we are type-checking+ -- indefinite packages.+ TcSession+ | backend dflags /= NoBackend+ -> EnumSet.insert Opt_WriteInterface (generalFlags dflags)+ _ -> generalFlags dflags++ -- Setup all of the output directories according to our hierarchy+ , objectDir = Just (outdir objectDir)+ , hiDir = Just (outdir hiDir)+ , stubDir = Just (outdir stubDir)+ -- Unset output-file for non exe builds+ , outputFile_ = case session_type of+ ExeSession -> outputFile_ dflags+ _ -> Nothing+ , dynOutputFile_ = case session_type of+ ExeSession -> dynOutputFile_ dflags+ _ -> Nothing+ -- Clear the import path so we don't accidentally grab anything+ , importPaths = []+ -- Synthesize the flags+ , packageFlags = packageFlags dflags ++ map (\(uid0, rn) ->+ let uid = unwireUnit unit_state+ $ improveUnit unit_state+ $ renameHoleUnit unit_state (listToUFM insts) uid0+ in ExposePackage+ (showSDoc dflags+ (text "-unit-id" <+> ppr uid <+> ppr rn))+ (UnitIdArg uid) rn) deps+ }+ withTempSession mk_temp_env $ do+ dflags <- getSessionDynFlags+ -- pprTrace "flags" (ppr insts <> ppr deps) $ return ()+ setSessionDynFlags dflags -- calls initUnits+ do_this+ withBkpExeSession :: [(Unit, ModRenaming)] -> BkpM a -> BkpM a withBkpExeSession deps do_this = withBkpSession (Indefinite (UnitId (fsLit "main"))) [] deps ExeSession do_this@@ -278,11 +288,11 @@ -- any object files. let deps_w_rns = hsunitDeps (session == TcSession) (unLoc lunit) raw_deps = map fst deps_w_rns- dflags <- getDynFlags+ hsc_env <- getSession -- The compilation dependencies are just the appropriately filled -- in unit IDs which must be compiled before we can compile. let hsubst = listToUFM insts- deps0 = map (renameHoleUnit (unitState dflags) hsubst) raw_deps+ deps0 = map (renameHoleUnit (hsc_units hsc_env) hsubst) raw_deps -- Build dependencies OR make sure they make sense. BUT NOTE, -- we can only check the ones that are fully filled; the rest@@ -293,9 +303,8 @@ TcSession -> return () _ -> compileInclude (length deps0) (i, dep) - dflags <- getDynFlags -- IMPROVE IT- let deps = map (improveUnit (unitState dflags)) deps0+ let deps = map (improveUnit (hsc_units hsc_env)) deps0 mb_old_eps <- case session of TcSession -> fmap Just getEpsGhc@@ -324,7 +333,7 @@ $ home_mod_infos getOfiles (LM _ _ us) = map nameOfObject (filter isObject us) obj_files = concatMap getOfiles linkables- state = unitState (hsc_dflags hsc_env)+ state = hsc_units hsc_env let compat_fs = unitIdFS (indefUnit cid) compat_pn = PackageName compat_fs@@ -380,7 +389,7 @@ } - addPackage conf+ addUnit conf case mb_old_eps of Just old_eps -> updateEpsGhc_ (const old_eps) _ -> return ()@@ -400,22 +409,33 @@ when (failed ok) (liftIO $ exitWith (ExitFailure 1)) -- | Register a new virtual unit database containing a single unit-addPackage :: GhcMonad m => UnitInfo -> m ()-addPackage pkg = do- dflags <- GHC.getSessionDynFlags- case unitDatabases dflags of- Nothing -> panic "addPackage: called too early"- Just dbs -> do+addUnit :: GhcMonad m => UnitInfo -> m ()+addUnit u = do+ hsc_env <- getSession+ newdbs <- case hsc_unit_dbs hsc_env of+ Nothing -> panic "addUnit: called too early"+ Just dbs -> let newdb = UnitDatabase- { unitDatabasePath = "(in memory " ++ showSDoc dflags (ppr (unitId pkg)) ++ ")"- , unitDatabaseUnits = [pkg]+ { unitDatabasePath = "(in memory " ++ showSDoc (hsc_dflags hsc_env) (ppr (unitId u)) ++ ")"+ , unitDatabaseUnits = [u] }- GHC.setSessionDynFlags (dflags { unitDatabases = Just (dbs ++ [newdb]) })+ in return (dbs ++ [newdb]) -- added at the end because ordering matters+ (dbs,unit_state,home_unit) <- liftIO $ initUnits (hsc_dflags hsc_env) (Just newdbs)+ let unit_env = UnitEnv+ { ue_platform = targetPlatform (hsc_dflags hsc_env)+ , ue_namever = ghcNameVersion (hsc_dflags hsc_env)+ , ue_home_unit = home_unit+ , ue_units = unit_state+ }+ setSession $ hsc_env+ { hsc_unit_dbs = Just dbs+ , hsc_unit_env = unit_env+ } compileInclude :: Int -> (Int, Unit) -> BkpM () compileInclude n (i, uid) = do hsc_env <- getSession- let pkgs = unitState (hsc_dflags hsc_env)+ let pkgs = hsc_units hsc_env msgInclude (i, n) uid -- Check if we've compiled it already case uid of@@ -469,10 +489,6 @@ getBkpLevel :: BkpM Int getBkpLevel = bkp_level `fmap` getBkpEnv --- | Apply a function on 'DynFlags' on an 'HscEnv'-overHscDynFlags :: (DynFlags -> DynFlags) -> HscEnv -> HscEnv-overHscDynFlags f hsc_env = hsc_env { hsc_dflags = f (hsc_dflags hsc_env) }- -- | Run a 'BkpM' computation, with the nesting level bumped one. innerBkpM :: BkpM a -> BkpM a innerBkpM do_this =@@ -520,19 +536,28 @@ mkBackpackMsg :: BkpM Messager mkBackpackMsg = do level <- getBkpLevel- return $ \hsc_env mod_index recomp mod_summary ->+ return $ \hsc_env mod_index recomp node -> let dflags = hsc_dflags hsc_env- state = unitState dflags+ state = hsc_units hsc_env showMsg msg reason = backpackProgressMsg level dflags $ pprWithUnitState state $ showModuleIndex mod_index <>- msg <> showModMsg dflags (recompileRequired recomp) mod_summary+ msg <> showModMsg dflags (recompileRequired recomp) node <> reason- in case recomp of+ in case node of+ InstantiationNode _ ->+ case recomp of+ MustCompile -> showMsg (text "Instantiating ") empty+ UpToDate+ | verbosity (hsc_dflags hsc_env) >= 2 -> showMsg (text "Skipping ") empty+ | otherwise -> return ()+ RecompBecause reason -> showMsg (text "Instantiating ") (text " [" <> text reason <> text "]")+ ModuleNode _ ->+ case recomp of MustCompile -> showMsg (text "Compiling ") empty UpToDate- | verbosity (hsc_dflags hsc_env) >= 2 -> showMsg (text "Skipping ") empty- | otherwise -> return ()+ | verbosity (hsc_dflags hsc_env) >= 2 -> showMsg (text "Skipping ") empty+ | otherwise -> return () RecompBecause reason -> showMsg (text "Compiling ") (text " [" <> text reason <> text "]") -- | 'PprStyle' for Backpack messages; here we usually want the module to@@ -557,8 +582,9 @@ msgUnitId :: Unit -> BkpM () msgUnitId pk = do dflags <- getDynFlags+ hsc_env <- getSession level <- getBkpLevel- let state = unitState dflags+ let state = hsc_units hsc_env liftIO . backpackProgressMsg level dflags $ pprWithUnitState state $ text "Instantiating "@@ -568,8 +594,9 @@ msgInclude :: (Int,Int) -> Unit -> BkpM () msgInclude (i,n) uid = do dflags <- getDynFlags+ hsc_env <- getSession level <- getBkpLevel- let state = unitState dflags+ let state = hsc_units hsc_env liftIO . backpackProgressMsg level dflags $ pprWithUnitState state $ showModuleIndex (i, n) <> text "Including "@@ -663,6 +690,7 @@ hsunitModuleGraph :: HsUnit HsComponentId -> BkpM ModuleGraph hsunitModuleGraph unit = do hsc_env <- getSession+ let decls = hsunitBody unit pn = hsPackageName (unLoc (hsunitName unit)) home_unit = hsc_home_unit hsc_env@@ -677,16 +705,21 @@ -- 2. For each hole which does not already have an hsig file, -- create an "empty" hsig file to induce compilation for the -- requirement.- let node_map = Map.fromList [ ((ms_mod_name n, ms_hsc_src n == HsigFile), n)- | n <- nodes ]+ let hsig_set = Set.fromList+ [ ms_mod_name ms+ | ExtendedModSummary { emsModSummary = ms } <- nodes+ , ms_hsc_src ms == HsigFile+ ] req_nodes <- fmap catMaybes . forM (homeUnitInstantiations home_unit) $ \(mod_name, _) ->- let has_local = Map.member (mod_name, True) node_map- in if has_local+ if Set.member mod_name hsig_set then return Nothing- else fmap Just $ summariseRequirement pn mod_name+ else fmap (Just . extendModSummaryNoDeps) $ summariseRequirement pn mod_name+ -- Using extendModSummaryNoDeps here is okay because we're making a leaf node+ -- representing a signature that can't depend on any other unit. -- 3. Return the kaboodle- return $ mkModuleGraph $ nodes ++ req_nodes+ return $ mkModuleGraph' $+ (ModuleNode <$> (nodes ++ req_nodes)) ++ instantiationNodes (hsc_units hsc_env) summariseRequirement :: PackageName -> ModuleName -> BkpM ModSummary summariseRequirement pn mod_name = do@@ -739,14 +772,14 @@ -> HscSource -> Located ModuleName -> Maybe (Located HsModule)- -> BkpM ModSummary+ -> BkpM ExtendedModSummary summariseDecl pn hsc_src (L _ modname) (Just hsmod) = hsModuleToModSummary pn hsc_src modname hsmod summariseDecl _pn hsc_src lmodname@(L loc modname) Nothing = do hsc_env <- getSession let dflags = hsc_dflags hsc_env -- TODO: this looks for modules in the wrong place r <- liftIO $ summariseModule hsc_env- Map.empty -- GHC API recomp not supported+ emptyModNodeMap -- GHC API recomp not supported (hscSourceToIsBoot hsc_src) lmodname True -- Target lets you disallow, but not here@@ -766,7 +799,7 @@ -> HscSource -> ModuleName -> Located HsModule- -> BkpM ModSummary+ -> BkpM ExtendedModSummary hsModuleToModSummary pn hsc_src modname hsmod = do let imps = hsmodImports (unLoc hsmod)@@ -814,11 +847,13 @@ extra_sig_imports <- liftIO $ findExtraSigImports hsc_env hsc_src modname let normal_imports = map convImport (implicit_imports ++ ordinary_imps)- required_by_imports <- liftIO $ implicitRequirements hsc_env normal_imports+ (implicit_sigs, inst_deps) <- liftIO $ implicitRequirementsShallow hsc_env normal_imports -- So that Finder can find it, even though it doesn't exist... this_mod <- liftIO $ addHomeModuleToFinder hsc_env modname location- return ModSummary {+ return $ ExtendedModSummary+ { emsModSummary =+ ModSummary { ms_mod = this_mod, ms_hsc_src = hsc_src, ms_location = location,@@ -833,7 +868,7 @@ -- due to merging, requirements may end up with -- extra imports ++ extra_sig_imports- ++ required_by_imports,+ ++ ((,) Nothing . noLoc <$> implicit_sigs), -- This is our hack to get the parse tree to the right spot ms_parsed_mod = Just (HsParsedModule { hpm_module = hsmod,@@ -844,7 +879,9 @@ ms_obj_date = Nothing, -- TODO do this, but problem: hi_timestamp is BOGUS ms_iface_date = hi_timestamp, ms_hie_date = hie_timestamp- }+ }+ , emsInstantiatedUnits = inst_deps+ } -- | Create a new, externally provided hashed unit id from -- a hash.
compiler/GHC/Driver/CodeOutput.hs view
@@ -64,6 +64,7 @@ -} codeOutput :: DynFlags+ -> UnitState -> Module -> FilePath -> ModLocation@@ -77,7 +78,7 @@ [(ForeignSrcLang, FilePath)]{-foreign_fps-}, a) -codeOutput dflags this_mod filenm location foreign_stubs foreign_fps pkg_deps+codeOutput dflags unit_state this_mod filenm location foreign_stubs foreign_fps pkg_deps cmm_stream = do {@@ -104,7 +105,7 @@ ; return cmm } - ; stubs_exist <- outputForeignStubs dflags this_mod location foreign_stubs+ ; stubs_exist <- outputForeignStubs dflags unit_state this_mod location foreign_stubs ; a <- case backend dflags of NCG -> outputAsm dflags this_mod location filenm linted_cmm_stream@@ -190,10 +191,10 @@ ************************************************************************ -} -outputForeignStubs :: DynFlags -> Module -> ModLocation -> ForeignStubs+outputForeignStubs :: DynFlags -> UnitState -> Module -> ModLocation -> ForeignStubs -> IO (Bool, -- Header file created Maybe FilePath) -- C file created-outputForeignStubs dflags mod location stubs+outputForeignStubs dflags unit_state mod location stubs = do let stub_h = mkStubPaths dflags (moduleName mod) location stub_c <- newTempName dflags TFL_CurrentModule "c"@@ -220,7 +221,7 @@ -- we need the #includes from the rts package for the stub files let rts_includes =- let rts_pkg = unsafeLookupUnitId (unitState dflags) rtsUnitId in+ let rts_pkg = unsafeLookupUnitId unit_state rtsUnitId in concatMap mk_include (unitIncludes rts_pkg) mk_include i = "#include \"" ++ ST.unpack i ++ "\"\n"
compiler/GHC/Driver/Main.hs view
@@ -235,12 +235,16 @@ newHscEnv :: DynFlags -> IO HscEnv newHscEnv dflags = do- let home_unit = mkHomeUnitFromFlags dflags- eps_var <- newIORef (initExternalPackageState home_unit)+ -- we don't store the unit databases and the unit state to still+ -- allow `setSessionDynFlags` to be used to set unit db flags.+ eps_var <- newIORef (initExternalPackageState (homeUnitId_ dflags)) us <- mkSplitUniqSupply 'r' nc_var <- newIORef (initNameCache us knownKeyNames) fc_var <- newIORef emptyInstalledModuleEnv emptyLoader <- uninitializedLoader+ -- FIXME: it's sad that we have so many "unitialized" fields filled with+ -- empty stuff or lazy panics. We should have two kinds of HscEnv+ -- (initialized or not) instead and less fields that are mutable over time. return HscEnv { hsc_dflags = dflags , hsc_targets = [] , hsc_mod_graph = emptyMG@@ -252,9 +256,10 @@ , hsc_type_env_var = Nothing , hsc_interp = Nothing , hsc_loader = emptyLoader- , hsc_home_unit = home_unit+ , hsc_unit_env = panic "hsc_unit_env not initialized" , hsc_plugins = [] , hsc_static_plugins = []+ , hsc_unit_dbs = Nothing } -- -----------------------------------------------------------------------------@@ -280,7 +285,7 @@ -- | log warning in the monad, and if there are errors then -- throw a SourceError exception.-logWarningsReportErrors :: (Bag Warning, Bag Error) -> Hsc ()+logWarningsReportErrors :: (Bag PsWarning, Bag PsError) -> Hsc () logWarningsReportErrors (warnings,errors) = do let warns = fmap pprWarning warnings errs = fmap pprError errors@@ -289,7 +294,7 @@ -- | Log warnings and throw errors, assuming the messages -- contain at least one error (e.g. coming from PFailed)-handleWarningsThrowErrors :: (Bag Warning, Bag Error) -> Hsc a+handleWarningsThrowErrors :: (Bag PsWarning, Bag PsError) -> Hsc a handleWarningsThrowErrors (warnings, errors) = do let warns = fmap pprWarning warnings errs = fmap pprError errors@@ -670,7 +675,7 @@ -} -type Messager = HscEnv -> (Int,Int) -> RecompileRequired -> ModSummary -> IO ()+type Messager = HscEnv -> (Int,Int) -> RecompileRequired -> ModuleGraphNode -> IO () -- | This function runs GHC's frontend with recompilation -- avoidance. Specifically, it checks if recompilation is needed,@@ -693,8 +698,9 @@ hsc_env <- getHscEnv let msg what = case mHscMessage of- Just hscMessage -> hscMessage hsc_env mod_index what mod_summary- Nothing -> return ()+ -- We use extendModSummaryNoDeps because extra backpack deps are only needed for batch mode+ Just hscMessage -> hscMessage hsc_env mod_index what (ModuleNode (extendModSummaryNoDeps mod_summary))+ Nothing -> return () skip iface = do liftIO $ msg UpToDate@@ -702,8 +708,11 @@ compile mb_old_hash reason = do liftIO $ msg reason- (tc_result, _) <- hsc_typecheck False mod_summary Nothing- return $ Right (FrontendTypecheck tc_result, mb_old_hash)+ tc_result <- do+ let def ms = FrontendTypecheck . fst <$> hsc_typecheck False ms Nothing+ action <- getHooked hscFrontendHook def+ action mod_summary+ return $ Right (tc_result, mb_old_hash) stable = case source_modified of SourceUnmodifiedAndStable -> True@@ -1023,19 +1032,27 @@ return () batchMsg :: Messager-batchMsg hsc_env mod_index recomp mod_summary =- case recomp of- MustCompile -> showMsg (text "Compiling ") empty- UpToDate- | verbosity (hsc_dflags hsc_env) >= 2 -> showMsg (text "Skipping ") empty- | otherwise -> return ()- RecompBecause reason -> showMsg (text "Compiling ") (text " [" <> text reason <> text "]")+batchMsg hsc_env mod_index recomp node = case node of+ InstantiationNode _ ->+ case recomp of+ MustCompile -> showMsg (text "Instantiating ") empty+ UpToDate+ | verbosity (hsc_dflags hsc_env) >= 2 -> showMsg (text "Skipping ") empty+ | otherwise -> return ()+ RecompBecause reason -> showMsg (text "Instantiating ") (text " [" <> text reason <> text "]")+ ModuleNode _ ->+ case recomp of+ MustCompile -> showMsg (text "Compiling ") empty+ UpToDate+ | verbosity (hsc_dflags hsc_env) >= 2 -> showMsg (text "Skipping ") empty+ | otherwise -> return ()+ RecompBecause reason -> showMsg (text "Compiling ") (text " [" <> text reason <> text "]") where dflags = hsc_dflags hsc_env showMsg msg reason = compilationProgressMsg dflags $ (showModuleIndex mod_index <>- msg <> showModMsg dflags (recompileRequired recomp) mod_summary)+ msg <> showModMsg dflags (recompileRequired recomp) node) <> reason --------------------------------------------------------------@@ -1258,6 +1275,7 @@ where isModSafe :: HomeUnit -> Module -> SrcSpan -> Hsc (Bool, Set UnitId) isModSafe home_unit m l = do+ hsc_env <- getHscEnv dflags <- getDynFlags iface <- lookup' m case iface of@@ -1273,7 +1291,7 @@ -- check module is trusted safeM = trust `elem` [Sf_Safe, Sf_SafeInferred, Sf_Trustworthy] -- check package is trusted- safeP = packageTrusted dflags home_unit trust trust_own_pkg m+ safeP = packageTrusted dflags (hsc_units hsc_env) home_unit trust trust_own_pkg m -- pkg trust reqs pkgRs = S.fromList . map fst $ filter snd $ dep_pkgs $ mi_deps iface' -- warn if Safe module imports Safe-Inferred module.@@ -1293,7 +1311,7 @@ return (trust == Sf_Trustworthy, pkgRs) where- state = unitState dflags+ state = hsc_units hsc_env inferredImportWarn = unitBag $ makeIntoWarning (Reason Opt_WarnInferredSafeImports) $ mkWarnMsg dflags l (pkgQual state)@@ -1318,17 +1336,17 @@ -- 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.- packageTrusted :: DynFlags -> HomeUnit -> SafeHaskellMode -> Bool -> Module -> Bool- packageTrusted _ _ Sf_None _ _ = False -- shouldn't hit these cases- packageTrusted _ _ Sf_Ignore _ _ = False -- shouldn't hit these cases- packageTrusted _ _ Sf_Unsafe _ _ = False -- prefer for completeness.- packageTrusted dflags _ _ _ _- | not (packageTrustOn dflags) = True- packageTrusted _ _ Sf_Safe False _ = True- packageTrusted _ _ Sf_SafeInferred False _ = True- packageTrusted dflags home_unit _ _ m- | isHomeModule home_unit m = True- | otherwise = unitIsTrusted $ unsafeLookupUnit (unitState dflags) (moduleUnit m)+ packageTrusted :: DynFlags -> UnitState -> HomeUnit -> SafeHaskellMode -> Bool -> Module -> Bool+ packageTrusted dflags unit_state home_unit safe_mode trust_own_pkg mod =+ case safe_mode of+ Sf_None -> False -- shouldn't hit these cases+ Sf_Ignore -> False -- shouldn't hit these cases+ Sf_Unsafe -> False -- prefer for completeness.+ _ | not (packageTrustOn dflags) -> True+ Sf_Safe | not trust_own_pkg -> True+ Sf_SafeInferred | not trust_own_pkg -> True+ _ | isHomeModule home_unit mod -> True+ _ -> unitIsTrusted $ unsafeLookupUnit unit_state (moduleUnit m) lookup' :: Module -> Hsc (Maybe ModIface) lookup' m = do@@ -1349,8 +1367,9 @@ checkPkgTrust :: Set UnitId -> Hsc () checkPkgTrust pkgs = do dflags <- getDynFlags+ hsc_env <- getHscEnv let errors = S.foldr go [] pkgs- state = unitState dflags+ state = hsc_units hsc_env go pkg acc | unitIsTrusted $ unsafeLookupUnitId state pkg = acc@@ -1542,7 +1561,7 @@ (output_filename, (_stub_h_exists, stub_c_exists), foreign_fps, cg_infos) <- {-# SCC "codeOutput" #-}- codeOutput dflags this_mod output_filename location+ codeOutput dflags (hsc_units hsc_env) this_mod output_filename location foreign_stubs foreign_files dependencies rawcmms1 return (output_filename, stub_c_exists, foreign_fps, cg_infos) @@ -1575,7 +1594,7 @@ comp_bc <- byteCodeGen hsc_env this_mod prepd_binds data_tycons mod_breaks ------------------ Create f-x-dynamic C-side stuff ----- (_istub_h_exists, istub_c_exists)- <- outputForeignStubs dflags this_mod location foreign_stubs+ <- outputForeignStubs dflags (hsc_units hsc_env) this_mod location foreign_stubs return (istub_c_exists, comp_bc, spt_entries) ------------------------------@@ -1588,7 +1607,7 @@ cmm <- ioMsgMaybe $ do (warns,errs,cmm) <- withTiming dflags (text "ParseCmm"<+>brackets (text filename)) (\_ -> ())- $ parseCmmFile dflags filename+ $ parseCmmFile dflags home_unit filename return ((fmap pprWarning warns, fmap pprError errs), cmm) liftIO $ do dumpIfSet_dyn dflags Opt_D_dump_cmm_verbose_by_proc "Parsed Cmm" FormatCMM (pdoc platform cmm)@@ -1611,7 +1630,7 @@ FormatCMM (pdoc platform cmmgroup) rawCmms <- lookupHook (\x -> cmmToRawCmmHook x) (\dflgs _ -> cmmToRawCmm dflgs) dflags dflags Nothing (Stream.yield cmmgroup)- _ <- codeOutput dflags cmm_mod output_filename no_loc NoStubs [] []+ _ <- codeOutput dflags (hsc_units hsc_env) cmm_mod output_filename no_loc NoStubs [] [] rawCmms return () where
compiler/GHC/Driver/Make.hs view
@@ -1,5 +1,11 @@-{-# LANGUAGE BangPatterns, CPP, NondecreasingIndentation, ScopedTypeVariables #-}-{-# LANGUAGE RecordWildCards, NamedFieldPuns #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NondecreasingIndentation #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} @@ -14,6 +20,7 @@ module GHC.Driver.Make ( depanal, depanalE, depanalPartial, load, load', LoadHowMuch(..),+ instantiationNodes, downsweep, @@ -24,11 +31,13 @@ summariseModule, hscSourceToIsBoot, findExtraSigImports,- implicitRequirements,+ implicitRequirementsShallow, noModError, cyclicModuleErr, moduleGraphNodes, SummaryNode,- IsBootInterface(..)+ IsBootInterface(..),++ ModNodeMap(..), emptyModNodeMap, modNodeMapElems, modNodeMapLookup, modNodeMapInsert ) where #include "GhclibHsVersions.h"@@ -55,7 +64,9 @@ import GHC.Parser.Header import GHC.Parser.Errors.Ppr +import GHC.Iface.Load ( cannotFindModule ) import GHC.IfaceToCore ( typecheckIface )+import GHC.Iface.Recomp ( RecompileRequired ( MustCompile ) ) import GHC.Data.Bag ( unitBag, listToBag, unionManyBags, isEmptyBag ) import GHC.Data.Graph.Directed@@ -207,13 +218,37 @@ -- cached finder data. liftIO $ flushFinderCaches hsc_env - mod_summariesE <- liftIO $ downsweep hsc_env (mgModSummaries old_graph)- excluded_mods allow_dup_roots+ mod_summariesE <- liftIO $ downsweep+ hsc_env (mgExtendedModSummaries old_graph)+ excluded_mods allow_dup_roots let- (errs, mod_summaries) = partitionEithers mod_summariesE- mod_graph = mkModuleGraph mod_summaries+ (errs, mod_summaries) = partitionEithers mod_summariesE+ mod_graph = mkModuleGraph' $+ fmap ModuleNode mod_summaries ++ instantiationNodes (hsc_units hsc_env) return (unionManyBags errs, mod_graph) +-- | Collect the instantiations of dependencies to create 'InstantiationNode' work graph nodes.+-- These are used to represent the type checking that is done after+-- all the free holes (sigs in current package) relevant to that instantiation+-- are compiled. This is necessary to catch some instantiation errors.+--+-- In the future, perhaps more of the work of instantiation could be moved here,+-- instead of shoved in with the module compilation nodes. That could simplify+-- backpack, and maybe hs-boot too.+instantiationNodes :: UnitState -> [ModuleGraphNode]+instantiationNodes unit_state = InstantiationNode <$> iuids_to_check+ where+ iuids_to_check :: [InstantiatedUnit]+ iuids_to_check =+ nubSort $ concatMap goUnitId (explicitUnits unit_state)+ where+ goUnitId uid =+ [ recur+ | VirtUnit indef <- [uid]+ , inst <- instUnitInsts indef+ , recur <- (indef :) $ goUnitId $ moduleUnit $ snd inst+ ]+ -- Note [Missing home modules] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Sometimes user doesn't want GHC to pick up modules, not explicitly listed@@ -329,7 +364,7 @@ eps <- liftIO $ hscEPS hsc_env let dflags = hsc_dflags hsc_env- state = unitState dflags+ state = hsc_units hsc_env pit = eps_PIT eps let loadedPackages@@ -430,7 +465,8 @@ -- upsweep, and for removing from hpt all the modules -- not in strict downwards closure, during calls to compile. let mg2_with_srcimps :: [SCC ModSummary]- mg2_with_srcimps = topSortModuleGraph True mod_graph Nothing+ mg2_with_srcimps = filterToposortToModules $+ topSortModuleGraph True mod_graph Nothing -- If we can determine that any of the {-# SOURCE #-} imports -- are definitely unnecessary, then emit a warning.@@ -484,7 +520,8 @@ -- This graph should be cycle-free. -- If we're restricting the upsweep to a portion of the graph, we -- also want to retain everything that is still stable.- let full_mg :: [SCC ModSummary]+ let full_mg, partial_mg0, partial_mg, unstable_mg :: [SCC ModuleGraphNode]+ stable_mg :: [SCC ExtendedModSummary] full_mg = topSortModuleGraph False mod_graph Nothing maybe_top_mod = case how_much of@@ -492,7 +529,6 @@ LoadDependenciesOf m -> Just m _ -> Nothing - partial_mg0 :: [SCC ModSummary] partial_mg0 = topSortModuleGraph False mod_graph maybe_top_mod -- LoadDependenciesOf m: we want the upsweep to stop just@@ -501,15 +537,16 @@ partial_mg | LoadDependenciesOf _mod <- how_much = ASSERT( case last partial_mg0 of- AcyclicSCC ms -> ms_mod_name ms == _mod; _ -> False )+ AcyclicSCC (ModuleNode (ExtendedModSummary ms _)) -> ms_mod_name ms == _mod; _ -> False ) List.init partial_mg0 | otherwise = partial_mg0 stable_mg =- [ AcyclicSCC ms- | AcyclicSCC ms <- full_mg,- stable_mod_summary ms ]+ [ AcyclicSCC ems+ | AcyclicSCC (ModuleNode ems@(ExtendedModSummary ms _)) <- full_mg+ , stable_mod_summary ms+ ] stable_mod_summary ms = ms_mod_name ms `elementOfUniqSet` stable_obj ||@@ -519,12 +556,13 @@ -- NB. also keep cycles, we need to emit an error message later unstable_mg = filter not_stable partial_mg where not_stable (CyclicSCC _) = True- not_stable (AcyclicSCC ms)+ not_stable (AcyclicSCC (InstantiationNode _)) = True+ not_stable (AcyclicSCC (ModuleNode (ExtendedModSummary ms _))) = not $ stable_mod_summary ms -- Load all the stable modules first, before attempting to load -- an unstable module (#7231).- mg = stable_mg ++ unstable_mg+ mg = fmap (fmap ModuleNode) stable_mg ++ unstable_mg -- clean up between compilations let cleanup = cleanCurrentModuleTempFiles . hsc_dflags@@ -545,7 +583,8 @@ -- available; this should equal the domain of hpt3. -- Get in in a roughly top .. bottom order (hence reverse). - let modsDone = reverse modsUpswept+ let nodesDone = reverse modsUpswept+ (_, modsDone) = partitionNodes nodesDone -- Try and do linking in some form, depending on whether the -- upsweep was completely or only partially successful.@@ -569,12 +608,13 @@ let ofile = outputFile dflags let no_hs_main = gopt Opt_NoHsMain dflags let- main_mod = mainModIs dflags+ main_mod = mainModIs hsc_env a_root_is_Main = mgElemModule mod_graph main_mod do_linking = a_root_is_Main || no_hs_main || ghcLink dflags == LinkDynLib || ghcLink dflags == LinkStaticLib -- link everything together- linkresult <- liftIO $ link (ghcLink dflags) dflags do_linking (hsc_HPT hsc_env1)+ unit_env <- hsc_unit_env <$> getSession+ linkresult <- liftIO $ link (ghcLink dflags) dflags unit_env do_linking (hsc_HPT hsc_env1) if ghcLink dflags == LinkBinary && isJust ofile && not do_linking then do@@ -595,12 +635,13 @@ do liftIO $ debugTraceMsg dflags 2 (text "Upsweep partially successful.") let modsDone_names- = map ms_mod modsDone+ = map (ms_mod . emsModSummary) modsDone let mods_to_zap_names = findPartiallyCompletedCycles modsDone_names mg2_with_srcimps let (mods_to_clean, mods_to_keep) =- partition ((`Set.member` mods_to_zap_names).ms_mod) modsDone+ partition ((`Set.member` mods_to_zap_names).ms_mod) $+ emsModSummary <$> modsDone hsc_env1 <- getSession let hpt4 = hsc_HPT hsc_env1 -- We must change the lifetime to TFL_CurrentModule for any temp@@ -632,11 +673,20 @@ ASSERT( just_linkables ) do -- Link everything together- linkresult <- liftIO $ link (ghcLink dflags) dflags False hpt5+ unit_env <- hsc_unit_env <$> getSession+ linkresult <- liftIO $ link (ghcLink dflags) dflags unit_env False hpt5 modifySession $ \hsc_env -> hsc_env{ hsc_HPT = hpt5 } loadFinish Failed linkresult +partitionNodes+ :: [ModuleGraphNode]+ -> ( [InstantiatedUnit]+ , [ExtendedModSummary]+ )+partitionNodes ns = partitionEithers $ flip fmap ns $ \case+ InstantiationNode x -> Left x+ ModuleNode x -> Right x -- | Finish up after a load. loadFinish :: GhcMonad m => SuccessFlag -> SuccessFlag -> m SuccessFlag@@ -691,7 +741,7 @@ !mod_graph = hsc_mod_graph env mainModuleSrcPath :: Maybe String mainModuleSrcPath = do- ms <- mgLookupModule mod_graph (mainModIs dflags)+ ms <- mgLookupModule mod_graph (mainModIs env) ml_hs_file (ms_location ms) name = fmap dropExtension mainModuleSrcPath @@ -936,11 +986,11 @@ -- | The graph of modules to compile and their corresponding result 'MVar' and -- 'LogQueue'.-type CompilationGraph = [(ModSummary, MVar SuccessFlag, LogQueue)]+type CompilationGraph = [(ModuleGraphNode, MVar SuccessFlag, LogQueue)] -- | Build a 'CompilationGraph' out of a list of strongly-connected modules, -- also returning the first, if any, encountered module cycle.-buildCompGraph :: [SCC ModSummary] -> IO (CompilationGraph, Maybe [ModSummary])+buildCompGraph :: [SCC ModuleGraphNode] -> IO (CompilationGraph, Maybe [ModuleGraphNode]) buildCompGraph [] = return ([], Nothing) buildCompGraph (scc:sccs) = case scc of AcyclicSCC ms -> do@@ -958,7 +1008,8 @@ -- We need to treat boot modules specially when building compilation graphs, -- since they break cycles. Regular source files and signature files are treated -- equivalently.-type BuildModule = ModuleWithIsBoot+data BuildModule = BuildModule_Unit {-# UNPACK #-} !InstantiatedUnit | BuildModule_Module {-# UNPACK #-} !ModuleWithIsBoot+ deriving (Eq, Ord) -- | Tests if an 'HscSource' is a boot file, primarily for constructing elements -- of 'BuildModule'. We conflate signatures and modules because they are bound@@ -968,14 +1019,24 @@ hscSourceToIsBoot HsBootFile = IsBoot hscSourceToIsBoot _ = NotBoot -mkBuildModule :: ModSummary -> BuildModule-mkBuildModule ms = GWIB+mkBuildModule :: ModuleGraphNode -> BuildModule+mkBuildModule = \case+ InstantiationNode x -> BuildModule_Unit x+ ModuleNode ems -> BuildModule_Module $ mkBuildModule0 (emsModSummary ems)++mkHomeBuildModule :: ModuleGraphNode -> NodeKey+mkHomeBuildModule = \case+ InstantiationNode x -> NodeKey_Unit x+ ModuleNode ems -> NodeKey_Module $ mkHomeBuildModule0 (emsModSummary ems)++mkBuildModule0 :: ModSummary -> ModuleWithIsBoot+mkBuildModule0 ms = GWIB { gwib_mod = ms_mod ms , gwib_isBoot = isBootSummary ms } -mkHomeBuildModule :: ModSummary -> ModuleNameWithIsBoot-mkHomeBuildModule ms = GWIB+mkHomeBuildModule0 :: ModSummary -> ModuleNameWithIsBoot+mkHomeBuildModule0 ms = GWIB { gwib_mod = moduleName $ ms_mod ms , gwib_isBoot = isBootSummary ms }@@ -991,16 +1052,13 @@ -> HomePackageTable -> StableModules -> (HscEnv -> IO ())- -> [SCC ModSummary]+ -> [SCC ModuleGraphNode] -> m (SuccessFlag,- [ModSummary])+ [ModuleGraphNode]) parUpsweep n_jobs mHscMessage old_hpt stable_mods cleanup sccs = do hsc_env <- getSession let dflags = hsc_dflags hsc_env - when (not (null (instantiatedUnitsToCheck dflags))) $- throwGhcException (ProgramError "Backpack typechecking not supported with -j")- -- The bits of shared state we'll be using: -- The global HscEnv is updated with the module's HMI when a module@@ -1046,16 +1104,19 @@ -- NB: For convenience, the last module of each loop (aka the module that -- finishes the loop) is prepended to the beginning of the loop. let graph = map fstOf3 (reverse comp_graph)- boot_modules = mkModuleSet [ms_mod ms | ms <- graph, isBootSummary ms == IsBoot]+ boot_modules = mkModuleSet+ [ms_mod ms | ModuleNode (ExtendedModSummary ms _) <- graph, isBootSummary ms == IsBoot] comp_graph_loops = go graph boot_modules where remove ms bm = case isBootSummary ms of IsBoot -> delModuleSet bm (ms_mod ms) NotBoot -> bm go [] _ = []- go mg@(ms:mss) boot_modules+ go (InstantiationNode _ : mss) boot_modules+ = go mss boot_modules+ go mg@(mnode@(ModuleNode (ExtendedModSummary ms _)) : mss) boot_modules | Just loop <- getModLoop ms mg (`elemModuleSet` boot_modules)- = map mkBuildModule (ms:loop) : go mss (remove ms boot_modules)+ = map mkBuildModule (mnode : loop) : go mss (remove ms boot_modules) | otherwise = go mss (remove ms boot_modules) @@ -1072,12 +1133,20 @@ -- compile this module. let { spawnWorkers = forM comp_graph_w_idx $ \((mod,!mvar,!log_queue),!mod_idx) -> forkIOWithUnmask $ \unmask -> do- liftIO $ label_self $ unwords- [ "worker --make thread"- , "for module"- , show (moduleNameString (ms_mod_name mod))- , "number"- , show mod_idx+ liftIO $ label_self $ unwords $ concat+ [ [ "worker --make thread" ]+ , case mod of+ InstantiationNode iuid ->+ [ "for instantiation of unit"+ , show $ VirtUnit iuid+ ]+ ModuleNode ems ->+ [ "for module"+ , show (moduleNameString (ms_mod_name (emsModSummary ems)))+ ]+ , ["number"+ , show mod_idx+ ] ] -- Replace the default log_action with one that writes each -- message to the module's log_queue. The main thread will@@ -1095,11 +1164,17 @@ -- Unmask asynchronous exceptions and perform the thread-local -- work to compile the module (see parUpsweep_one). m_res <- MC.try $ unmask $ prettyPrintGhcErrors lcl_dflags $- parUpsweep_one mod home_mod_map comp_graph_loops- lcl_dflags (hsc_home_unit hsc_env)- mHscMessage cleanup- par_sem hsc_env_var old_hpt_var- stable_mods mod_idx (length sccs)+ case mod of+ InstantiationNode iuid -> do+ hsc_env <- readMVar hsc_env_var+ liftIO $ upsweep_inst hsc_env mHscMessage mod_idx (length sccs) iuid+ pure Succeeded+ ModuleNode ems ->+ parUpsweep_one (emsModSummary ems) home_mod_map comp_graph_loops+ lcl_dflags (hsc_home_unit hsc_env)+ mHscMessage cleanup+ par_sem hsc_env_var old_hpt_var+ stable_mods mod_idx (length sccs) res <- case m_res of Right flag -> return flag@@ -1222,7 +1297,7 @@ parUpsweep_one mod home_mod_map comp_graph_loops lcl_dflags home_unit mHscMessage cleanup par_sem hsc_env_var old_hpt_var stable_mods mod_index num_mods = do - let this_build_mod = mkBuildModule mod+ let this_build_mod = mkBuildModule0 mod let home_imps = map unLoc $ ms_home_imps mod let home_src_imps = map unLoc $ ms_home_srcimps mod@@ -1231,7 +1306,7 @@ let textual_deps = Set.fromList $ zipWith f home_imps (repeat NotBoot) ++ zipWith f home_src_imps (repeat IsBoot)- where f mn isBoot = GWIB+ where f mn isBoot = BuildModule_Module $ GWIB { gwib_mod = mkHomeModule home_unit mn , gwib_isBoot = isBoot }@@ -1265,29 +1340,36 @@ -- The loop that this module will finish. After this module successfully -- compiles, this loop is going to get re-typechecked.- let finish_loop = listToMaybe- [ tail loop | loop <- comp_graph_loops- , head loop == this_build_mod ]+ let finish_loop :: Maybe [ModuleWithIsBoot]+ finish_loop = listToMaybe+ [ flip mapMaybe (tail loop) $ \case+ BuildModule_Unit _ -> Nothing+ BuildModule_Module ms -> Just ms+ | loop <- comp_graph_loops+ , head loop == BuildModule_Module this_build_mod+ ] -- If this module finishes a loop then it must depend on all the other -- modules in that loop because the entire module loop is going to be -- re-typechecked once this module gets compiled. These extra dependencies -- are this module's "internal" loop dependencies, because this module is -- inside the loop in question.- let int_loop_deps = Set.fromList $+ let int_loop_deps :: Set.Set BuildModule+ int_loop_deps = Set.fromList $ case finish_loop of Nothing -> []- Just loop -> filter (/= this_build_mod) loop+ Just loop -> BuildModule_Module <$> filter (/= this_build_mod) loop -- If this module depends on a module within a loop then it must wait for -- that loop to get re-typechecked, i.e. it must wait on the module that -- finishes that loop. These extra dependencies are this module's -- "external" loop dependencies, because this module is outside of the -- loop(s) in question.- let ext_loop_deps = Set.fromList+ let ext_loop_deps :: Set.Set BuildModule+ ext_loop_deps = Set.fromList [ head loop | loop <- comp_graph_loops , any (`Set.member` textual_deps) loop- , this_build_mod `notElem` loop ]+ , BuildModule_Module this_build_mod `notElem` loop ] let all_deps = foldl1 Set.union [textual_deps, int_loop_deps, ext_loop_deps]@@ -1295,7 +1377,8 @@ -- All of the module's home-module dependencies. let home_deps_with_idx = [ home_dep | dep <- Set.toList all_deps- , Just home_dep <- [Map.lookup dep home_mod_map] ]+ , Just home_dep <- [Map.lookup dep home_mod_map]+ ] -- Sort the list of dependencies in reverse-topological order. This way, by -- the time we get woken up by the result of an earlier dependency,@@ -1398,14 +1481,14 @@ -- There better had not be any cyclic groups here -- we check for them. upsweep :: forall m- . GhcMonad m+ . GhcMonad m => Maybe Messager -> HomePackageTable -- ^ HPT from last time round (pruned) -> StableModules -- ^ stable modules (see checkStability) -> (HscEnv -> IO ()) -- ^ How to clean up unwanted tmp files- -> [SCC ModSummary] -- ^ Mods to do (the worklist)+ -> [SCC ModuleGraphNode] -- ^ Mods to do (the worklist) -> m (SuccessFlag,- [ModSummary])+ [ModuleGraphNode]) -- ^ Returns: -- -- 1. A flag whether the complete upsweep was successful.@@ -1413,58 +1496,63 @@ -- 3. A list of modules which succeeded loading. upsweep mHscMessage old_hpt stable_mods cleanup sccs = do- dflags <- getSessionDynFlags (res, done) <- upsweep' old_hpt emptyMG sccs 1 (length sccs)- (instantiatedUnitsToCheck dflags) done_holes- return (res, reverse $ mgModSummaries done)+ return (res, reverse $ mgModSummaries' done) where- done_holes = emptyUniqSet-- keep_going this_mods old_hpt done mods mod_index nmods uids_to_check done_holes = do- let sum_deps ms (AcyclicSCC mod) =- if any (flip elem $ unfilteredEdges False mod) ms- then mkHomeBuildModule mod:ms- else ms+ keep_going+ :: [NodeKey]+ -> HomePackageTable+ -> ModuleGraph+ -> [SCC ModuleGraphNode]+ -> Int+ -> Int+ -> m (SuccessFlag, ModuleGraph)+ keep_going this_mods old_hpt done mods mod_index nmods = do+ let sum_deps ms (AcyclicSCC iuidOrMod) =+ if any (flip elem $ unfilteredEdges False iuidOrMod) $ ms+ then mkHomeBuildModule iuidOrMod : ms+ else ms sum_deps ms _ = ms dep_closure = foldl' sum_deps this_mods mods dropped_ms = drop (length this_mods) (reverse dep_closure)- prunable (AcyclicSCC mod) = elem (mkHomeBuildModule mod) dep_closure+ prunable (AcyclicSCC node) = elem (mkHomeBuildModule node) dep_closure prunable _ = False mods' = filter (not . prunable) mods nmods' = nmods - length dropped_ms when (not $ null dropped_ms) $ do dflags <- getSessionDynFlags- liftIO $ fatalErrorMsg dflags (keepGoingPruneErr $ gwib_mod <$> dropped_ms)- (_, done') <- upsweep' old_hpt done mods' (mod_index+1) nmods' uids_to_check done_holes+ liftIO $ fatalErrorMsg dflags (keepGoingPruneErr $ dropped_ms)+ (_, done') <- upsweep' old_hpt done mods' (mod_index+1) nmods' return (Failed, done') upsweep' :: HomePackageTable -> ModuleGraph- -> [SCC ModSummary]+ -> [SCC ModuleGraphNode] -> Int -> Int- -> [Unit]- -> UniqSet ModuleName -> m (SuccessFlag, ModuleGraph) upsweep' _old_hpt done- [] _ _ uids_to_check _- = do hsc_env <- getSession- liftIO . runHsc hsc_env $ mapM_ (ioMsgMaybe . tcRnCheckUnit hsc_env) uids_to_check- return (Succeeded, done)+ [] _ _+ = return (Succeeded, done) upsweep' _old_hpt done- (CyclicSCC ms:mods) mod_index nmods uids_to_check done_holes+ (CyclicSCC ms : mods) mod_index nmods = do dflags <- getSessionDynFlags liftIO $ fatalErrorMsg dflags (cyclicModuleErr ms) if gopt Opt_KeepGoing dflags then keep_going (mkHomeBuildModule <$> ms) old_hpt done mods mod_index nmods- uids_to_check done_holes else return (Failed, done) upsweep' old_hpt done- (AcyclicSCC mod:mods) mod_index nmods uids_to_check done_holes+ (AcyclicSCC (InstantiationNode iuid) : mods) mod_index nmods+ = do hsc_env <- getSession+ liftIO $ upsweep_inst hsc_env mHscMessage mod_index nmods iuid+ upsweep' old_hpt done mods (mod_index+1) nmods++ upsweep' old_hpt done+ (AcyclicSCC (ModuleNode ems@(ExtendedModSummary mod _)) : mods) mod_index nmods = do -- putStrLn ("UPSWEEP_MOD: hpt = " ++ -- show (map (moduleUserString.moduleName.mi_module.hm_iface) -- (moduleEnvElts (hsc_HPT hsc_env)))@@ -1472,18 +1560,6 @@ hsc_env <- getSession - -- TODO: Cache this, so that we don't repeatedly re-check- -- our imports when you run --make.- let (ready_uids, uids_to_check')- = partition (\uid -> isEmptyUniqDSet- (unitFreeModuleHoles uid `uniqDSetMinusUniqSet` done_holes))- uids_to_check- done_holes'- | ms_hsc_src mod == HsigFile- = addOneToUniqSet done_holes (ms_mod_name mod)- | otherwise = done_holes- liftIO . runHsc hsc_env $ mapM_ (ioMsgMaybe . tcRnCheckUnit hsc_env) ready_uids- -- Remove unwanted tmp files between compilations liftIO (cleanup hsc_env) @@ -1513,8 +1589,7 @@ Nothing -> do dflags <- getSessionDynFlags if gopt Opt_KeepGoing dflags- then keep_going [mkHomeBuildModule mod] old_hpt done mods mod_index nmods- uids_to_check done_holes+ then keep_going [NodeKey_Module $ mkHomeBuildModule0 mod] old_hpt done mods mod_index nmods else return (Failed, done) Just mod_info -> do let this_mod = ms_mod_name mod@@ -1534,7 +1609,7 @@ IsBoot -> old_hpt NotBoot -> delFromHpt old_hpt this_mod - done' = extendMG done mod+ done' = extendMG done ems -- fixup our HomePackageTable after we've finished compiling -- a mutually-recursive loop. We have to do this again@@ -1556,19 +1631,7 @@ , spt <- spts ] - upsweep' old_hpt1 done' mods (mod_index+1) nmods uids_to_check' done_holes'---- | Return a list of instantiated units to type check from the UnitState.------ Use explicit (instantiated) units as roots and also return their--- instantiations that are themselves instantiations and so on recursively.-instantiatedUnitsToCheck :: DynFlags -> [Unit]-instantiatedUnitsToCheck dflags =- nubSort $ concatMap goUnit (explicitUnits (unitState dflags))- where- goUnit HoleUnit = []- goUnit (RealUnit _) = []- goUnit uid@(VirtUnit i) = uid : concatMap (goUnit . moduleUnit . snd) (instUnitInsts i)+ upsweep' old_hpt1 done' mods (mod_index+1) nmods maybeGetIfaceDate :: DynFlags -> ModLocation -> IO (Maybe UTCTime) maybeGetIfaceDate dflags location@@ -1579,6 +1642,19 @@ | otherwise = return Nothing +upsweep_inst :: HscEnv+ -> Maybe Messager+ -> Int -- index of module+ -> Int -- total number of modules+ -> InstantiatedUnit+ -> IO ()+upsweep_inst hsc_env mHscMessage mod_index nmods iuid = do+ case mHscMessage of+ Just hscMessage -> hscMessage hsc_env (mod_index, nmods) MustCompile (InstantiationNode iuid)+ Nothing -> return ()+ runHsc hsc_env $ ioMsgMaybe $ tcRnCheckUnit hsc_env $ VirtUnit iuid+ pure ()+ -- | Compile a single module. Always produce a Linkable for it if -- successful. If no compilation happened, return the old Linkable. upsweep_mod :: HscEnv@@ -1864,13 +1940,17 @@ | Just loop <- getModLoop ms mss appearsAsBoot -- SOME hs-boot files should still -- get used, just not the loop-closer.- , let non_boot = filter (\l -> not (isBootSummary l == IsBoot &&- ms_mod l == ms_mod ms)) loop+ , let non_boot = flip mapMaybe loop $ \case+ InstantiationNode _ -> Nothing+ ModuleNode ems -> do+ let l = emsModSummary ems+ guard $ not $ isBootSummary l == IsBoot && ms_mod l == ms_mod ms+ pure l = typecheckLoop (hsc_dflags hsc_env) hsc_env (map ms_mod_name non_boot) | otherwise = return hsc_env where- mss = mgModSummaries graph+ mss = mgModSummaries' graph appearsAsBoot = (`elemModuleSet` mgBootModules graph) -- | Given a non-boot ModSummary @ms@ of a module, for which there exists a@@ -1911,9 +1991,9 @@ -- getModLoop :: ModSummary- -> [ModSummary]+ -> [ModuleGraphNode] -> (Module -> Bool) -- check if a module appears as a boot module in 'graph'- -> Maybe [ModSummary]+ -> Maybe [ModuleGraphNode] getModLoop ms graph appearsAsBoot | isBootSummary ms == NotBoot , appearsAsBoot this_mod@@ -1944,12 +2024,12 @@ old_hpt = hsc_HPT hsc_env hmis = map (expectJust "typecheckLoop" . lookupHpt old_hpt) mods -reachableBackwards :: ModuleName -> [ModSummary] -> [ModSummary]+reachableBackwards :: ModuleName -> [ModuleGraphNode] -> [ModuleGraphNode] reachableBackwards mod summaries = [ node_payload node | node <- reachableG (transposeG graph) root ] where -- the rest just sets up the graph: (graph, lookup_node) = moduleGraphNodes False summaries- root = expectJust "reachableBackwards" (lookup_node $ GWIB mod IsBoot)+ root = expectJust "reachableBackwards" (lookup_node $ NodeKey_Module $ GWIB mod IsBoot) -- --------------------------------------------------------------------------- --@@ -1960,7 +2040,7 @@ -> ModuleGraph -> Maybe ModuleName -- ^ Root module name. If @Nothing@, use the full graph.- -> [SCC ModSummary]+ -> [SCC ModuleGraphNode] -- ^ Calculate SCCs of the module graph, possibly dropping the hi-boot nodes -- The resulting list of strongly-connected-components is in topologically -- sorted order, starting with the module(s) at the bottom of the@@ -1979,7 +2059,7 @@ topSortModuleGraph drop_hs_boot_nodes module_graph mb_root_mod = map (fmap summaryNodeSummary) $ stronglyConnCompG initial_graph where- summaries = mgModSummaries module_graph+ summaries = mgModSummaries' module_graph -- stronglyConnCompG flips the original order, so if we reverse -- the summaries we get a stable topological sort. (graph, lookup_node) =@@ -1992,22 +2072,22 @@ -- the specified module. We do this by building a graph with -- the full set of nodes, and determining the reachable set from -- the specified node.- let root | Just node <- lookup_node $ GWIB root_mod NotBoot+ let root | Just node <- lookup_node $ NodeKey_Module $ GWIB root_mod NotBoot , graph `hasVertexG` node = node | otherwise = throwGhcException (ProgramError "module does not exist") in graphFromEdgedVerticesUniq (seq root (reachableG graph root)) -type SummaryNode = Node Int ModSummary+type SummaryNode = Node Int ModuleGraphNode summaryNodeKey :: SummaryNode -> Int summaryNodeKey = node_key -summaryNodeSummary :: SummaryNode -> ModSummary+summaryNodeSummary :: SummaryNode -> ModuleGraphNode summaryNodeSummary = node_payload --- | Collect the immediate dependencies of a module from its ModSummary,+-- | Collect the immediate dependencies of a ModuleGraphNode, -- optionally avoiding hs-boot dependencies. -- If the drop_hs_boot_nodes flag is False, and if this is a .hs and there is -- an equivalent .hs-boot, add a link from the former to the latter. This@@ -2015,69 +2095,103 @@ -- .hs, by introducing a cycle. Additionally, it ensures that we will always -- process the .hs-boot before the .hs, and so the HomePackageTable will always -- have the most up to date information.-unfilteredEdges :: Bool -> ModSummary -> [ModuleNameWithIsBoot]-unfilteredEdges drop_hs_boot_nodes ms =- (flip GWIB hs_boot_key . unLoc <$> ms_home_srcimps ms) ++- (flip GWIB NotBoot . unLoc <$> ms_home_imps ms) ++- [ GWIB (ms_mod_name ms) IsBoot- | not $ drop_hs_boot_nodes || ms_hsc_src ms == HsBootFile- ]+unfilteredEdges :: Bool -> ModuleGraphNode -> [NodeKey]+unfilteredEdges drop_hs_boot_nodes = \case+ InstantiationNode iuid ->+ NodeKey_Module . flip GWIB NotBoot <$> uniqDSetToList (instUnitHoles iuid)+ ModuleNode (ExtendedModSummary ms bds) ->+ (NodeKey_Module . flip GWIB hs_boot_key . unLoc <$> ms_home_srcimps ms) +++ (NodeKey_Module . flip GWIB NotBoot . unLoc <$> ms_home_imps ms) +++ [ NodeKey_Module $ GWIB (ms_mod_name ms) IsBoot+ | not $ drop_hs_boot_nodes || ms_hsc_src ms == HsBootFile+ ] +++ [ NodeKey_Unit inst_unit+ | inst_unit <- bds+ ] where -- Drop hs-boot nodes by using HsSrcFile as the key hs_boot_key | drop_hs_boot_nodes = NotBoot -- is regular mod or signature | otherwise = IsBoot -moduleGraphNodes :: Bool -> [ModSummary]- -> (Graph SummaryNode, ModuleNameWithIsBoot -> Maybe SummaryNode)+moduleGraphNodes :: Bool -> [ModuleGraphNode]+ -> (Graph SummaryNode, NodeKey -> Maybe SummaryNode) moduleGraphNodes drop_hs_boot_nodes summaries = (graphFromEdgedVerticesUniq nodes, lookup_node) where numbered_summaries = zip summaries [1..] - lookup_node :: ModuleNameWithIsBoot -> Maybe SummaryNode- lookup_node mnwib = Map.lookup mnwib node_map+ lookup_node :: NodeKey -> Maybe SummaryNode+ lookup_node key = Map.lookup key (unNodeMap node_map) - lookup_key :: ModuleNameWithIsBoot -> Maybe Int+ lookup_key :: NodeKey -> Maybe Int lookup_key = fmap summaryNodeKey . lookup_node node_map :: NodeMap SummaryNode- node_map = Map.fromList [ (mkHomeBuildModule s, node)- | node <- nodes- , let s = summaryNodeSummary node- ]+ node_map = NodeMap $+ Map.fromList [ (mkHomeBuildModule s, node)+ | node <- nodes+ , let s = summaryNodeSummary node+ ] -- We use integers as the keys for the SCC algorithm nodes :: [SummaryNode] nodes = [ DigraphNode s key $ out_edge_keys $ unfilteredEdges drop_hs_boot_nodes s | (s, key) <- numbered_summaries -- Drop the hi-boot ones if told to do so- , not (isBootSummary s == IsBoot && drop_hs_boot_nodes)+ , case s of+ InstantiationNode _ -> True+ ModuleNode ems -> not $ isBootSummary (emsModSummary ems) == IsBoot && drop_hs_boot_nodes ] - out_edge_keys :: [ModuleNameWithIsBoot] -> [Int]+ out_edge_keys :: [NodeKey] -> [Int] out_edge_keys = mapMaybe lookup_key -- If we want keep_hi_boot_nodes, then we do lookup_key with -- IsBoot; else False --- The nodes of the graph are keyed by (mod, is boot?) pairs+-- The nodes of the graph are keyed by (mod, is boot?) pairs for the current+-- modules, and indefinite unit IDs for dependencies which are instantiated with+-- our holes.+-- -- NB: hsig files show up as *normal* nodes (not boot!), since they don't -- participate in cycles (for now)-type NodeKey = ModuleNameWithIsBoot-type NodeMap a = Map.Map NodeKey a+type ModNodeKey = ModuleNameWithIsBoot+newtype ModNodeMap a = ModNodeMap { unModNodeMap :: Map.Map ModNodeKey a }+ deriving (Functor, Traversable, Foldable) -msKey :: ModSummary -> NodeKey-msKey (ModSummary { ms_mod = mod, ms_hsc_src = boot })- = GWIB- { gwib_mod = moduleName mod- , gwib_isBoot = hscSourceToIsBoot boot- }+emptyModNodeMap :: ModNodeMap a+emptyModNodeMap = ModNodeMap Map.empty -mkNodeMap :: [ModSummary] -> NodeMap ModSummary-mkNodeMap summaries = Map.fromList [ (msKey s, s) | s <- summaries]+modNodeMapInsert :: ModNodeKey -> a -> ModNodeMap a -> ModNodeMap a+modNodeMapInsert k v (ModNodeMap m) = ModNodeMap (Map.insert k v m) -nodeMapElts :: NodeMap a -> [a]-nodeMapElts = Map.elems+modNodeMapElems :: ModNodeMap a -> [a]+modNodeMapElems (ModNodeMap m) = Map.elems m +modNodeMapLookup :: ModNodeKey -> ModNodeMap a -> Maybe a+modNodeMapLookup k (ModNodeMap m) = Map.lookup k m++data NodeKey = NodeKey_Unit {-# UNPACK #-} !InstantiatedUnit | NodeKey_Module {-# UNPACK #-} !ModNodeKey+ deriving (Eq, Ord)++newtype NodeMap a = NodeMap { unNodeMap :: Map.Map NodeKey a }+ deriving (Functor, Traversable, Foldable)++msKey :: ModSummary -> ModNodeKey+msKey = mkHomeBuildModule0++mkNodeKey :: ModuleGraphNode -> NodeKey+mkNodeKey = \case+ InstantiationNode x -> NodeKey_Unit x+ ModuleNode x -> NodeKey_Module $ mkHomeBuildModule0 (emsModSummary x)++pprNodeKey :: NodeKey -> SDoc+pprNodeKey (NodeKey_Unit iu) = ppr iu+pprNodeKey (NodeKey_Module mk) = ppr mk++mkNodeMap :: [ExtendedModSummary] -> ModNodeMap ExtendedModSummary+mkNodeMap summaries = ModNodeMap $ Map.fromList+ [ (msKey $ emsModSummary s, s) | s <- summaries]+ -- | 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@@ -2115,16 +2229,17 @@ -- module, plus one for any hs-boot files. The imports of these nodes -- are all there, including the imports of non-home-package modules. downsweep :: HscEnv- -> [ModSummary] -- Old summaries+ -> [ExtendedModSummary]+ -- ^ Old summaries -> [ModuleName] -- Ignore dependencies on these; treat -- them as if they were package modules -> Bool -- True <=> allow multiple targets to have -- the same module name; this is -- very useful for ghc -M- -> IO [Either ErrorMessages ModSummary]- -- The elts of [ModSummary] all have distinct- -- (Modules, IsBoot) identifiers, unless the Bool is true- -- in which case there can be repeats+ -> IO [Either ErrorMessages ExtendedModSummary]+ -- The non-error elements of the returned list all have distinct+ -- (Modules, IsBoot) identifiers, unless the Bool is true in+ -- which case there can be repeats downsweep hsc_env old_summaries excl_mods allow_dup_roots = do rootSummaries <- mapM getRootSummary roots@@ -2143,18 +2258,20 @@ Interpreter -> enableCodeGenForUnboxedTuplesOrSums default_backend map0 _ -> return map0 if null errs- then pure $ concat $ nodeMapElts map1+ then pure $ concat $ modNodeMapElems map1 else pure $ map Left errs where- calcDeps = msDeps+ -- TODO(@Ericson2314): Probably want to include backpack instantiations+ -- in the map eventually for uniformity+ calcDeps (ExtendedModSummary ms _bkp_deps) = msDeps ms dflags = hsc_dflags hsc_env roots = hsc_targets hsc_env - old_summary_map :: NodeMap ModSummary+ old_summary_map :: ModNodeMap ExtendedModSummary old_summary_map = mkNodeMap old_summaries - getRootSummary :: Target -> IO (Either ErrorMessages ModSummary)+ getRootSummary :: Target -> IO (Either ErrorMessages ExtendedModSummary) getRootSummary (Target (TargetFile file mb_phase) obj_allowed maybe_buf) = do exists <- liftIO $ doesFileExist file if exists || isJust maybe_buf@@ -2176,40 +2293,46 @@ -- name, so we have to check that there aren't multiple root files -- defining the same module (otherwise the duplicates will be silently -- ignored, leading to confusing behaviour).- checkDuplicates :: NodeMap [Either ErrorMessages ModSummary] -> IO ()+ checkDuplicates+ :: ModNodeMap+ [Either ErrorMessages+ ExtendedModSummary]+ -> IO () checkDuplicates root_map | allow_dup_roots = return () | null dup_roots = return ()- | otherwise = liftIO $ multiRootsErr dflags (head dup_roots)+ | otherwise = liftIO $ multiRootsErr dflags (emsModSummary <$> head dup_roots) where- dup_roots :: [[ModSummary]] -- Each at least of length 2- dup_roots = filterOut isSingleton $ map rights $ nodeMapElts root_map+ dup_roots :: [[ExtendedModSummary]] -- Each at least of length 2+ dup_roots = filterOut isSingleton $ map rights $ modNodeMapElems root_map loop :: [GenWithIsBoot (Located ModuleName)] -- Work list: process these modules- -> NodeMap [Either ErrorMessages ModSummary]+ -> ModNodeMap [Either ErrorMessages ExtendedModSummary] -- Visited set; the range is a list because -- the roots can have the same module names -- if allow_dup_roots is True- -> IO (NodeMap [Either ErrorMessages ModSummary])+ -> IO (ModNodeMap [Either ErrorMessages ExtendedModSummary]) -- The result is the completed NodeMap loop [] done = return done loop (s : ss) done- | Just summs <- Map.lookup key done+ | Just summs <- modNodeMapLookup key done = if isSingleton summs then loop ss done else- do { multiRootsErr dflags (rights summs); return Map.empty }+ do { multiRootsErr dflags (emsModSummary <$> rights summs)+ ; return (ModNodeMap Map.empty)+ } | otherwise = do mb_s <- summariseModule hsc_env old_summary_map is_boot wanted_mod True Nothing excl_mods case mb_s of Nothing -> loop ss done- Just (Left e) -> loop ss (Map.insert key [Left e] done)+ Just (Left e) -> loop ss (modNodeMapInsert key [Left e] done) Just (Right s)-> do new_map <-- loop (calcDeps s) (Map.insert key [Right s] done)+ loop (calcDeps s) (modNodeMapInsert key [Right s] done) loop ss new_map where GWIB { gwib_mod = L loc mod, gwib_isBoot = is_boot } = s@@ -2225,8 +2348,8 @@ -- and .o file locations to be temporary files. -- See Note [-fno-code mode] enableCodeGenForTH :: HomeUnit -> Backend- -> NodeMap [Either ErrorMessages ModSummary]- -> IO (NodeMap [Either ErrorMessages ModSummary])+ -> ModNodeMap [Either ErrorMessages ExtendedModSummary]+ -> IO (ModNodeMap [Either ErrorMessages ExtendedModSummary]) enableCodeGenForTH home_unit = enableCodeGenWhen condition should_modify TFL_CurrentModule TFL_GhcSession where@@ -2245,8 +2368,8 @@ -- This is used in order to load code that uses unboxed tuples -- or sums into GHCi while still allowing some code to be interpreted. enableCodeGenForUnboxedTuplesOrSums :: Backend- -> NodeMap [Either ErrorMessages ModSummary]- -> IO (NodeMap [Either ErrorMessages ModSummary])+ -> ModNodeMap [Either ErrorMessages ExtendedModSummary]+ -> IO (ModNodeMap [Either ErrorMessages ExtendedModSummary]) enableCodeGenForUnboxedTuplesOrSums = enableCodeGenWhen condition should_modify TFL_GhcSession TFL_CurrentModule where@@ -2271,12 +2394,13 @@ -> TempFileLifetime -> TempFileLifetime -> Backend- -> NodeMap [Either ErrorMessages ModSummary]- -> IO (NodeMap [Either ErrorMessages ModSummary])+ -> ModNodeMap [Either ErrorMessages ExtendedModSummary]+ -> IO (ModNodeMap [Either ErrorMessages ExtendedModSummary]) enableCodeGenWhen condition should_modify staticLife dynLife bcknd nodemap = traverse (traverse (traverse enable_code_gen)) nodemap where- enable_code_gen ms+ enable_code_gen :: ExtendedModSummary -> IO ExtendedModSummary+ enable_code_gen (ExtendedModSummary ms bkp_deps) | ModSummary { ms_mod = ms_mod , ms_location = ms_location@@ -2302,22 +2426,23 @@ then return (ml_hi_file ms_location, ml_obj_file ms_location) else (,) <$> (new_temp_file (hiSuf_ dflags) (dynHiSuf_ dflags)) <*> (new_temp_file (objectSuf_ dflags) (dynObjectSuf_ dflags))- return $- ms- { ms_location =- ms_location {ml_hi_file = hi_file, ml_obj_file = o_file}- , ms_hspp_opts = updOptLevel 0 $ dflags {backend = bcknd}- }- | otherwise = return ms+ let ms' = ms+ { ms_location =+ ms_location {ml_hi_file = hi_file, ml_obj_file = o_file}+ , ms_hspp_opts = updOptLevel 0 $ dflags {backend = bcknd}+ }+ pure (ExtendedModSummary ms' bkp_deps)+ | otherwise = return (ExtendedModSummary ms bkp_deps) needs_codegen_set = transitive_deps_set [ ms- | mss <- Map.elems nodemap- , Right ms <- mss+ | mss <- modNodeMapElems nodemap+ , Right (ExtendedModSummary { emsModSummary = ms }) <- mss , condition ms ] -- find the set of all transitive dependencies of a list of modules.+ transitive_deps_set :: [ModSummary] -> Set.Set Module transitive_deps_set modSums = foldl' go Set.empty modSums where go marked_mods ms@ModSummary{ms_mod}@@ -2330,17 +2455,20 @@ -- means we don't have to think about boot modules here. | dep <- msDeps ms , NotBoot == gwib_isBoot dep- , dep_ms_0 <- toList $ Map.lookup (unLoc <$> dep) nodemap+ , dep_ms_0 <- toList $ modNodeMapLookup (unLoc <$> dep) nodemap , dep_ms_1 <- toList $ dep_ms_0- , dep_ms <- toList $ dep_ms_1+ , (ExtendedModSummary { emsModSummary = dep_ms }) <- toList $ dep_ms_1 ] new_marked_mods = Set.insert ms_mod marked_mods in foldl' go new_marked_mods deps -mkRootMap :: [ModSummary] -> NodeMap [Either ErrorMessages ModSummary]-mkRootMap summaries = Map.insertListWith (flip (++))- [ (msKey s, [Right s]) | s <- summaries ]- Map.empty+mkRootMap+ :: [ExtendedModSummary]+ -> ModNodeMap [Either ErrorMessages ExtendedModSummary]+mkRootMap summaries = ModNodeMap $ Map.insertListWith+ (flip (++))+ [ (msKey $ emsModSummary s, [Right s]) | s <- summaries ]+ Map.empty -- | Returns the dependencies of the ModSummary s. -- A wrinkle is that for a {-# SOURCE #-} import we return@@ -2376,12 +2504,12 @@ summariseFile :: HscEnv- -> [ModSummary] -- old summaries+ -> [ExtendedModSummary] -- old summaries -> FilePath -- source file name -> Maybe Phase -- start phase -> Bool -- object code allowed? -> Maybe (StringBuffer,UTCTime)- -> IO (Either ErrorMessages ModSummary)+ -> IO (Either ErrorMessages ExtendedModSummary) summariseFile hsc_env old_summaries src_fn mb_phase obj_allowed maybe_buf -- we can use a cached summary if one is available and the@@ -2389,7 +2517,7 @@ -- by source file, rather than module name as we do in summarise. | Just old_summary <- findSummaryBySourceFile old_summaries src_fn = do- let location = ms_location old_summary+ let location = ms_location $ emsModSummary old_summary dflags = hsc_dflags hsc_env src_timestamp <- get_src_timestamp@@ -2438,21 +2566,27 @@ , nms_preimps = preimps } -findSummaryBySourceFile :: [ModSummary] -> FilePath -> Maybe ModSummary-findSummaryBySourceFile summaries file- = case [ ms | ms <- summaries, HsSrcFile <- [ms_hsc_src ms],- expectJust "findSummaryBySourceFile" (ml_hs_file (ms_location ms)) == file ] of- [] -> Nothing- (x:_) -> Just x+findSummaryBySourceFile :: [ExtendedModSummary] -> FilePath -> Maybe ExtendedModSummary+findSummaryBySourceFile summaries file = case+ [ ms+ | ms <- summaries+ , HsSrcFile <- [ms_hsc_src $ emsModSummary ms]+ , let derived_file = ml_hs_file $ ms_location $ emsModSummary ms+ , expectJust "findSummaryBySourceFile" derived_file == file+ ]+ of+ [] -> Nothing+ (x:_) -> Just x checkSummaryTimestamp :: HscEnv -> DynFlags -> Bool -> IsBootInterface- -> (UTCTime -> IO (Either e ModSummary))- -> ModSummary -> ModLocation -> UTCTime- -> IO (Either e ModSummary)+ -> (UTCTime -> IO (Either e ExtendedModSummary))+ -> ExtendedModSummary -> ModLocation -> UTCTime+ -> IO (Either e ExtendedModSummary) checkSummaryTimestamp hsc_env dflags obj_allowed is_boot new_summary- old_summary location src_timestamp+ (ExtendedModSummary { emsModSummary = old_summary, emsInstantiatedUnits = bkp_deps})+ location src_timestamp | ms_hs_date old_summary == src_timestamp && not (gopt Opt_ForceRecomp (hsc_dflags hsc_env)) = do -- update the object-file timestamp@@ -2473,11 +2607,15 @@ hi_timestamp <- maybeGetIfaceDate dflags location hie_timestamp <- modificationTimeIfExists (ml_hie_file location) - return $ Right old_summary- { ms_obj_date = obj_timestamp- , ms_iface_date = hi_timestamp- , ms_hie_date = hie_timestamp- }+ return $ Right+ ( ExtendedModSummary { emsModSummary = old_summary+ { ms_obj_date = obj_timestamp+ , ms_iface_date = hi_timestamp+ , ms_hie_date = hie_timestamp+ }+ , emsInstantiatedUnits = bkp_deps+ }+ ) | otherwise = -- source changed: re-summarise.@@ -2486,25 +2624,26 @@ -- Summarise a module, and pick up source and timestamp. summariseModule :: HscEnv- -> NodeMap ModSummary -- Map of old summaries+ -> ModNodeMap ExtendedModSummary+ -- ^ Map of old summaries -> IsBootInterface -- True <=> a {-# SOURCE #-} import -> Located ModuleName -- Imported module to be summarised -> Bool -- object code allowed? -> Maybe (StringBuffer, UTCTime) -> [ModuleName] -- Modules to exclude- -> IO (Maybe (Either ErrorMessages ModSummary)) -- Its new summary+ -> IO (Maybe (Either ErrorMessages ExtendedModSummary)) -- Its new summary summariseModule hsc_env old_summary_map is_boot (L loc wanted_mod) obj_allowed maybe_buf excl_mods | wanted_mod `elem` excl_mods = return Nothing - | Just old_summary <- Map.lookup+ | Just old_summary <- modNodeMapLookup (GWIB { gwib_mod = wanted_mod, gwib_isBoot = is_boot }) old_summary_map = do -- Find its new timestamp; all the -- ModSummaries in the old map have valid ml_hs_files- let location = ms_location old_summary+ let location = ms_location $ emsModSummary old_summary src_fn = expectJust "summariseModule" (ml_hs_file location) -- check the modification time on the source file, and@@ -2529,7 +2668,7 @@ check_timestamp old_summary location src_fn = checkSummaryTimestamp hsc_env dflags obj_allowed is_boot- (new_summary location (ms_mod old_summary) src_fn)+ (new_summary location (ms_mod $ emsModSummary old_summary) src_fn) old_summary location find_it = do@@ -2626,7 +2765,7 @@ , nms_preimps :: PreprocessedImports } -makeNewModSummary :: HscEnv -> MakeNewModSummary -> IO ModSummary+makeNewModSummary :: HscEnv -> MakeNewModSummary -> IO ExtendedModSummary makeNewModSummary hsc_env MakeNewModSummary{..} = do let PreprocessedImports{..} = nms_preimps let dflags = hsc_dflags hsc_env@@ -2643,24 +2782,30 @@ hie_timestamp <- modificationTimeIfExists (ml_hie_file nms_location) extra_sig_imports <- findExtraSigImports hsc_env nms_hsc_src pi_mod_name- required_by_imports <- implicitRequirements hsc_env pi_theimps+ (implicit_sigs, inst_deps) <- implicitRequirementsShallow hsc_env pi_theimps - return $ ModSummary- { ms_mod = nms_mod- , ms_hsc_src = nms_hsc_src- , ms_location = nms_location- , ms_hspp_file = pi_hspp_fn- , ms_hspp_opts = pi_local_dflags- , ms_hspp_buf = Just pi_hspp_buf- , ms_parsed_mod = Nothing- , ms_srcimps = pi_srcimps- , ms_textual_imps =- pi_theimps ++ extra_sig_imports ++ required_by_imports- , ms_hs_date = nms_src_timestamp- , ms_iface_date = hi_timestamp- , ms_hie_date = hie_timestamp- , ms_obj_date = obj_timestamp- }+ return $ ExtendedModSummary+ { emsModSummary =+ ModSummary+ { ms_mod = nms_mod+ , ms_hsc_src = nms_hsc_src+ , ms_location = nms_location+ , ms_hspp_file = pi_hspp_fn+ , ms_hspp_opts = pi_local_dflags+ , ms_hspp_buf = Just pi_hspp_buf+ , ms_parsed_mod = Nothing+ , ms_srcimps = pi_srcimps+ , ms_textual_imps =+ pi_theimps +++ extra_sig_imports +++ ((,) Nothing . noLoc <$> implicit_sigs)+ , ms_hs_date = nms_src_timestamp+ , ms_iface_date = hi_timestamp+ , ms_hie_date = hie_timestamp+ , ms_obj_date = obj_timestamp+ }+ , emsInstantiatedUnits = inst_deps+ } getObjTimestamp :: ModLocation -> IsBootInterface -> IO (Maybe UTCTime) getObjTimestamp location is_boot@@ -2740,10 +2885,10 @@ (\_ -> setLogAction (log_action dflags) >> printDeferredDiagnostics) (\_ -> f) -noModError :: DynFlags -> SrcSpan -> ModuleName -> FindResult -> ErrMsg+noModError :: HscEnv -> SrcSpan -> ModuleName -> FindResult -> ErrMsg -- ToDo: we don't have a proper line number for this error-noModError dflags loc wanted_mod err- = mkPlainErrMsg dflags loc $ cannotFindModule dflags wanted_mod err+noModError hsc_env loc wanted_mod err+ = mkPlainErrMsg (hsc_dflags hsc_env) loc $ cannotFindModule hsc_env wanted_mod err noHsFileErr :: DynFlags -> SrcSpan -> String -> ErrorMessages noHsFileErr dflags loc path@@ -2765,42 +2910,64 @@ mod = ms_mod summ1 files = map (expectJust "checkDup" . ml_hs_file . ms_location) summs -keepGoingPruneErr :: [ModuleName] -> SDoc+keepGoingPruneErr :: [NodeKey] -> SDoc keepGoingPruneErr ms = vcat (( text "-fkeep-going in use, removing the following" <+> text "dependencies and continuing:"):- map (nest 6 . ppr) ms )+ map (nest 6 . pprNodeKey) ms ) -cyclicModuleErr :: [ModSummary] -> SDoc+cyclicModuleErr :: [ModuleGraphNode] -> SDoc -- From a strongly connected component we find -- a single cycle to report cyclicModuleErr mss = ASSERT( not (null mss) ) case findCycle graph of Nothing -> text "Unexpected non-cycle" <+> ppr mss- Just path -> vcat [ text "Module imports form a cycle:"- , nest 2 (show_path path) ]+ Just path0 -> vcat+ [ case partitionNodes path0 of+ ([],_) -> text "Module imports form a cycle:"+ (_,[]) -> text "Module instantiations form a cycle:"+ _ -> text "Module imports and instantiations form a cycle:"+ , nest 2 (show_path path0)] where- graph :: [Node NodeKey ModSummary]- graph = [ DigraphNode ms (msKey ms) (get_deps ms) | ms <- mss]+ graph :: [Node NodeKey ModuleGraphNode]+ graph =+ [ DigraphNode+ { node_payload = ms+ , node_key = mkNodeKey ms+ , node_dependencies = get_deps ms+ }+ | ms <- mss+ ] - get_deps :: ModSummary -> [NodeKey]- get_deps ms =- [ GWIB { gwib_mod = unLoc m, gwib_isBoot = IsBoot }- | m <- ms_home_srcimps ms ] ++- [ GWIB { gwib_mod = unLoc m, gwib_isBoot = NotBoot }- | m <- ms_home_imps ms ]+ get_deps :: ModuleGraphNode -> [NodeKey]+ get_deps = \case+ InstantiationNode iuid ->+ [ NodeKey_Module $ GWIB { gwib_mod = hole, gwib_isBoot = NotBoot }+ | hole <- uniqDSetToList $ instUnitHoles iuid+ ]+ ModuleNode (ExtendedModSummary ms bds) ->+ [ NodeKey_Module $ GWIB { gwib_mod = unLoc m, gwib_isBoot = IsBoot }+ | m <- ms_home_srcimps ms ] +++ [ NodeKey_Module $ GWIB { gwib_mod = unLoc m, gwib_isBoot = NotBoot }+ | m <- ms_home_imps ms ] +++ [ NodeKey_Unit inst_unit+ | inst_unit <- bds+ ] - show_path [] = panic "show_path"- show_path [m] = text "module" <+> ppr_ms m- <+> text "imports itself"- show_path (m1:m2:ms) = vcat ( nest 7 (text "module" <+> ppr_ms m1)- : nest 6 (text "imports" <+> ppr_ms m2)+ show_path :: [ModuleGraphNode] -> SDoc+ show_path [] = panic "show_path"+ show_path [m] = ppr_node m <+> text "imports itself"+ show_path (m1:m2:ms) = vcat ( nest 6 (ppr_node m1)+ : nest 6 (text "imports" <+> ppr_node m2) : go ms ) where- go [] = [text "which imports" <+> ppr_ms m1]- go (m:ms) = (text "which imports" <+> ppr_ms m) : go ms+ go [] = [text "which imports" <+> ppr_node m1]+ go (m:ms) = (text "which imports" <+> ppr_node m) : go ms + ppr_node :: ModuleGraphNode -> SDoc+ ppr_node (ModuleNode m) = text "module" <+> ppr_ms (emsModSummary m)+ ppr_node (InstantiationNode u) = text "instantiated unit" <+> ppr u ppr_ms :: ModSummary -> SDoc ppr_ms ms = quotes (ppr (moduleName (ms_mod ms))) <+>
compiler/GHC/Driver/MakeFile.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-} ----------------------------------------------------------------------------- --@@ -33,6 +34,8 @@ import GHC.Data.FastString import GHC.SysTools.FileCleanup +import GHC.Iface.Load (cannotFindModule)+ import GHC.Unit.Module import GHC.Unit.Module.ModSummary import GHC.Unit.Module.Graph@@ -184,7 +187,7 @@ -> [ModuleName] -> FilePath -> Handle -- Write dependencies to here- -> SCC ModSummary+ -> SCC ModuleGraphNode -> IO () -- Write suitable dependencies to handle -- Always:@@ -203,9 +206,17 @@ processDeps dflags _ _ _ _ (CyclicSCC nodes) = -- There shouldn't be any cycles; report them- throwGhcExceptionIO (ProgramError (showSDoc dflags $ GHC.cyclicModuleErr nodes))+ throwGhcExceptionIO $ ProgramError $+ showSDoc dflags $ GHC.cyclicModuleErr nodes -processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC node)+processDeps dflags _ _ _ _ (AcyclicSCC (InstantiationNode node))+ = -- There shouldn't be any backpack instantiations; report them as well+ throwGhcExceptionIO $ ProgramError $+ showSDoc dflags $+ vcat [ text "Unexpected backpack instantiation in dependency graph while constructing Makefile:"+ , nest 2 $ ppr node ]++processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC (ModuleNode (ExtendedModSummary node _))) = do { let extra_suffixes = depSuffixes dflags include_pkg_deps = depIncludePkgDeps dflags src_file = msHsFilePath node@@ -279,7 +290,7 @@ fail -> let dflags = hsc_dflags hsc_env in throwOneError $ mkPlainErrMsg dflags srcloc $- cannotFindModule dflags imp fail+ cannotFindModule hsc_env imp fail } -----------------------------@@ -369,10 +380,12 @@ | otherwise = putMsg dflags (hang (text "Module cycles found:") 2 pp_cycles) where+ topoSort = filterToposortToModules $+ GHC.topSortModuleGraph True module_graph Nothing cycles :: [[ModSummary]] cycles =- [ c | CyclicSCC c <- GHC.topSortModuleGraph True module_graph Nothing ]+ [ c | CyclicSCC c <- topoSort ] pp_cycles = vcat [ (text "---------- Cycle" <+> int n <+> ptext (sLit "----------")) $$ pprCycle c $$ blankLine@@ -400,8 +413,8 @@ loop_breaker = head boot_only all_others = tail boot_only ++ others- groups =- GHC.topSortModuleGraph True (mkModuleGraph all_others) Nothing+ groups = filterToposortToModules $+ GHC.topSortModuleGraph True (mkModuleGraph $ extendModSummaryNoDeps <$> all_others) Nothing pp_ms summary = text mod_str <> text (take (20 - length mod_str) (repeat ' ')) <+> (pp_imps empty (map snd (ms_imps summary)) $$
compiler/GHC/Driver/Pipeline.hs view
@@ -65,8 +65,6 @@ import GHC.Linker.ExtraObj import GHC.Linker.Dynamic-import GHC.Linker.MacOS-import GHC.Linker.Unit import GHC.Linker.Static import GHC.Linker.Types @@ -96,6 +94,7 @@ import GHC.Types.SourceError import GHC.Unit+import GHC.Unit.Env import GHC.Unit.State import GHC.Unit.Finder import GHC.Unit.Module.ModSummary@@ -340,14 +339,18 @@ current_dir = takeDirectory basename old_paths = includePaths dflags2 !prevailing_dflags = hsc_dflags hsc_env0+ loadAsByteCode+ | Just (Target _ obj _) <- findTarget summary (hsc_targets hsc_env0)+ , not obj+ = True+ | otherwise = False -- Figure out which backend we're using (bcknd, dflags3) -- #8042: When module was loaded with `*` prefix in ghci, but DynFlags -- suggest to generate object code (which may happen in case -fobject-code -- was set), force it to generate byte-code. This is NOT transitive and -- only applies to direct targets.- | Just (Target _ obj _) <- findTarget summary (hsc_targets hsc_env0)- , not obj+ | loadAsByteCode = (Interpreter, dflags2 { backend = Interpreter }) | otherwise = (backend dflags, dflags2)@@ -363,7 +366,10 @@ -- -fforce-recomp should also work with --make force_recomp = gopt Opt_ForceRecomp dflags source_modified- | force_recomp = SourceModified+ -- #8042: Usually pre-compiled code is preferred to be loaded in ghci+ -- if available. So, if the "*" prefix was used, force recompilation+ -- to make sure byte-code is loaded.+ | force_recomp || loadAsByteCode = SourceModified | otherwise = source_modified0 always_do_basic_recompilation_check = case bcknd of@@ -479,10 +485,11 @@ -- by shortening the library names, or start putting libraries into the same -- folders, such that one runpath would be sufficient for multiple/all -- libraries.-link :: GhcLink -- interactive or batch- -> DynFlags -- dynamic flags- -> Bool -- attempt linking in batch mode?- -> HomePackageTable -- what to link+link :: GhcLink -- ^ interactive or batch+ -> DynFlags -- ^ dynamic flags+ -> UnitEnv -- ^ unit environment+ -> Bool -- ^ attempt linking in batch mode?+ -> HomePackageTable -- ^ what to link -> IO SuccessFlag -- For the moment, in the batch linker, we don't bother to tell doLink@@ -492,7 +499,7 @@ -- exports main, i.e., we have good reason to believe that linking -- will succeed. -link ghcLink dflags+link ghcLink dflags unit_env = lookupHook linkHook l dflags ghcLink dflags where l LinkInMemory _ _ _@@ -505,24 +512,25 @@ = return Succeeded l LinkBinary dflags batch_attempt_linking hpt- = link' dflags batch_attempt_linking hpt+ = link' dflags unit_env batch_attempt_linking hpt l LinkStaticLib dflags batch_attempt_linking hpt- = link' dflags batch_attempt_linking hpt+ = link' dflags unit_env batch_attempt_linking hpt l LinkDynLib dflags batch_attempt_linking hpt- = link' dflags batch_attempt_linking hpt+ = link' dflags unit_env batch_attempt_linking hpt panicBadLink :: GhcLink -> a panicBadLink other = panic ("link: GHC not built to link this way: " ++ show other) -link' :: DynFlags -- dynamic flags- -> Bool -- attempt linking in batch mode?- -> HomePackageTable -- what to link+link' :: DynFlags -- ^ dynamic flags+ -> UnitEnv -- ^ unit environment+ -> Bool -- ^ attempt linking in batch mode?+ -> HomePackageTable -- ^ what to link -> IO SuccessFlag -link' dflags batch_attempt_linking hpt+link' dflags unit_env batch_attempt_linking hpt | batch_attempt_linking = do let@@ -551,7 +559,7 @@ platform = targetPlatform dflags exe_file = exeFileName platform staticLink (outputFile dflags) - linking_needed <- linkingNeeded dflags staticLink linkables pkg_deps+ linking_needed <- linkingNeeded dflags unit_env staticLink linkables pkg_deps if not (gopt Opt_ForceRecomp dflags) && not linking_needed then do debugTraceMsg dflags 2 (text exe_file <+> text "is up to date, linking not required.")@@ -566,7 +574,7 @@ LinkStaticLib -> linkStaticLib LinkDynLib -> linkDynLibCheck other -> panicBadLink other- link dflags obj_files pkg_deps+ link dflags unit_env obj_files pkg_deps debugTraceMsg dflags 3 (text "link: done") @@ -579,13 +587,14 @@ return Succeeded -linkingNeeded :: DynFlags -> Bool -> [Linkable] -> [UnitId] -> IO Bool-linkingNeeded dflags staticLink linkables pkg_deps = do+linkingNeeded :: DynFlags -> UnitEnv -> Bool -> [Linkable] -> [UnitId] -> IO Bool+linkingNeeded dflags unit_env staticLink linkables pkg_deps = do -- if the modification time on the executable is later than the -- modification times on all of the objects and libraries, then omit -- linking (unless the -fforce-recomp flag was given).- let platform = targetPlatform dflags- exe_file = exeFileName platform staticLink (outputFile dflags)+ let platform = ue_platform unit_env+ unit_state = ue_units unit_env+ exe_file = exeFileName platform staticLink (outputFile dflags) e_exe_time <- tryIO $ getModificationUTCTime exe_file case e_exe_time of Left _ -> return True@@ -601,10 +610,9 @@ -- next, check libraries. XXX this only checks Haskell libraries, -- not extra_libraries or -l things from the command line.- let unit_state = unitState dflags- let pkg_hslibs = [ (collectLibraryPaths (ways dflags) [c], lib)+ let pkg_hslibs = [ (collectLibraryDirs (ways dflags) [c], lib) | Just c <- map (lookupUnitId unit_state) pkg_deps,- lib <- packageHsLibs dflags c ]+ lib <- unitHsLibs (ghcNameVersion dflags) (ways dflags) c ] pkg_libfiles <- mapM (uncurry (findHSLib platform (ways dflags))) pkg_hslibs if any isNothing pkg_libfiles then return True else do@@ -613,7 +621,7 @@ let (lib_errs,lib_times) = partitionEithers e_lib_times if not (null lib_errs) || any (t <) lib_times then return True- else checkLinkInfo dflags pkg_deps exe_file+ else checkLinkInfo dflags unit_env pkg_deps exe_file findHSLib :: Platform -> Ways -> [String] -> String -> IO (Maybe FilePath) findHSLib platform ws dirs lib = do@@ -631,7 +639,7 @@ oneShot :: HscEnv -> Phase -> [(String, Maybe Phase)] -> IO () oneShot hsc_env stop_phase srcs = do o_files <- mapM (compileFile hsc_env stop_phase) srcs- doLink (hsc_dflags hsc_env) stop_phase o_files+ doLink hsc_env stop_phase o_files compileFile :: HscEnv -> Phase -> (FilePath, Maybe Phase) -> IO FilePath compileFile hsc_env stop_phase (src, mb_phase) = do@@ -665,17 +673,20 @@ return out_file -doLink :: DynFlags -> Phase -> [FilePath] -> IO ()-doLink dflags stop_phase o_files+doLink :: HscEnv -> Phase -> [FilePath] -> IO ()+doLink hsc_env stop_phase o_files | not (isStopLn stop_phase) = return () -- We stopped before the linking phase | otherwise- = case ghcLink dflags of+ = let+ dflags = hsc_dflags hsc_env+ unit_env = hsc_unit_env hsc_env+ in case ghcLink dflags of NoLink -> return ()- LinkBinary -> linkBinary dflags o_files []- LinkStaticLib -> linkStaticLib dflags o_files []- LinkDynLib -> linkDynLibCheck dflags o_files []+ LinkBinary -> linkBinary dflags unit_env o_files []+ LinkStaticLib -> linkStaticLib dflags unit_env o_files []+ LinkDynLib -> linkDynLibCheck dflags unit_env o_files [] other -> panicBadLink other @@ -804,7 +815,18 @@ $ setDynamicNow $ dflags hsc_env' <- newHscEnv dflags'- _ <- runPipeline' start_phase hsc_env' env input_fn'+ (dbs,unit_state,home_unit) <- initUnits dflags' Nothing+ let unit_env = UnitEnv+ { ue_platform = targetPlatform dflags'+ , ue_namever = ghcNameVersion dflags'+ , ue_home_unit = home_unit+ , ue_units = unit_state+ }+ let hsc_env'' = hsc_env'+ { hsc_unit_env = unit_env+ , hsc_unit_dbs = Just dbs+ }+ _ <- runPipeline' start_phase hsc_env'' env input_fn' maybe_loc foreign_os return () return r@@ -874,7 +896,7 @@ case phase of HscOut {} -> do let noDynToo = do- (next_phase, output_fn) <- runHookedPhase phase input_fn dflags+ (next_phase, output_fn) <- runHookedPhase phase input_fn pipeLoop next_phase output_fn let dynToo = do -- if Opt_BuildDynamicToo is set and if the platform@@ -883,7 +905,7 @@ -- the non-dynamic ones. let dflags' = setDynamicNow dflags -- set "dynamicNow" setDynFlags dflags'- (next_phase, output_fn) <- runHookedPhase phase input_fn dflags'+ (next_phase, output_fn) <- runHookedPhase phase input_fn _ <- pipeLoop next_phase output_fn -- TODO: we probably shouldn't ignore the result of -- the dynamic compilation@@ -902,13 +924,13 @@ -- we set DynamicNow but we unset Opt_BuildDynamicToo so -- it's weird. _ -> do- (next_phase, output_fn) <- runHookedPhase phase input_fn dflags+ (next_phase, output_fn) <- runHookedPhase phase input_fn pipeLoop next_phase output_fn -runHookedPhase :: PhasePlus -> FilePath -> DynFlags- -> CompPipeline (PhasePlus, FilePath)-runHookedPhase pp input dflags =- lookupHook runPhaseHook runPhase dflags pp input dflags+runHookedPhase :: PhasePlus -> FilePath -> CompPipeline (PhasePlus, FilePath)+runHookedPhase pp input = do+ dflags <- hsc_dflags <$> getPipeSession+ lookupHook runPhaseHook runPhase dflags pp input -- ----------------------------------------------------------------------------- -- In each phase, we need to know into what filename to generate the@@ -1052,7 +1074,6 @@ -- runPhase :: PhasePlus -- ^ Run this phase -> FilePath -- ^ name of the input file- -> DynFlags -- ^ for convenience, we pass the current dflags in -> CompPipeline (PhasePlus, -- next phase to run FilePath) -- output filename @@ -1064,23 +1085,8 @@ ------------------------------------------------------------------------------- -- Unlit phase -runPhase (RealPhase (Unlit sf)) input_fn dflags- = do- output_fn <- phaseOutputFilename (Cpp sf)-- let flags = [ -- The -h option passes the file name for unlit to- -- put in a #line directive- GHC.SysTools.Option "-h"- -- See Note [Don't normalise input filenames].- , GHC.SysTools.Option $ escape input_fn- , GHC.SysTools.FileOption "" input_fn- , GHC.SysTools.FileOption "" output_fn- ]-- liftIO $ GHC.SysTools.runUnlit dflags flags-- return (RealPhase (Cpp sf), output_fn)- where+runPhase (RealPhase (Unlit sf)) input_fn = do+ let -- escape the characters \, ", and ', but don't try to escape -- Unicode or anything else (so we don't use Util.charToC -- here). If we get this wrong, then in@@ -1094,12 +1100,29 @@ escape (c:cs) = c : escape cs escape [] = [] + output_fn <- phaseOutputFilename (Cpp sf)++ let flags = [ -- The -h option passes the file name for unlit to+ -- put in a #line directive+ GHC.SysTools.Option "-h"+ -- See Note [Don't normalise input filenames].+ , GHC.SysTools.Option $ escape input_fn+ , GHC.SysTools.FileOption "" input_fn+ , GHC.SysTools.FileOption "" output_fn+ ]++ dflags <- hsc_dflags <$> getPipeSession+ liftIO $ GHC.SysTools.runUnlit dflags flags++ return (RealPhase (Cpp sf), output_fn)+ ------------------------------------------------------------------------------- -- Cpp phase : (a) gets OPTIONS out of file -- (b) runs cpp if necessary -runPhase (RealPhase (Cpp sf)) input_fn dflags0+runPhase (RealPhase (Cpp sf)) input_fn = do+ dflags0 <- getDynFlags src_opts <- liftIO $ getOptionsFromFile dflags0 input_fn (dflags1, unhandled_flags, warns) <- liftIO $ parseDynamicFilePragma dflags0 src_opts@@ -1116,7 +1139,9 @@ return (RealPhase (HsPp sf), input_fn) else do output_fn <- phaseOutputFilename (HsPp sf)- liftIO $ doCpp dflags1 True{-raw-}+ hsc_env <- getPipeSession+ liftIO $ doCpp (hsc_dflags hsc_env) (hsc_unit_env hsc_env)+ True{-raw-} input_fn output_fn -- re-read the pragmas now that we've preprocessed the file -- See #2464,#3457@@ -1135,8 +1160,9 @@ ------------------------------------------------------------------------------- -- HsPp phase -runPhase (RealPhase (HsPp sf)) input_fn dflags- = if not (gopt Opt_Pp dflags) then+runPhase (RealPhase (HsPp sf)) input_fn = do+ dflags <- getDynFlags+ if not (gopt Opt_Pp dflags) then -- no need to preprocess, just pass input file along -- to the next phase of the pipeline. return (RealPhase (Hsc sf), input_fn)@@ -1166,8 +1192,9 @@ -- Compilation of a single module, in "legacy" mode (_not_ under -- the direction of the compilation manager).-runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0+runPhase (RealPhase (Hsc src_flavour)) input_fn = do -- normal Hsc mode, not mkdependHS+ dflags0 <- getDynFlags PipeEnv{ stop_phase=stop, src_basename=basename,@@ -1270,7 +1297,8 @@ return (HscOut src_flavour mod_name result, panic "HscOut doesn't have an input filename") -runPhase (HscOut src_flavour mod_name result) _ dflags = do+runPhase (HscOut src_flavour mod_name result) _ = do+ dflags <- getDynFlags location <- getLocation src_flavour mod_name setModLocation location @@ -1335,14 +1363,18 @@ ----------------------------------------------------------------------------- -- Cmm phase -runPhase (RealPhase CmmCpp) input_fn dflags- = do output_fn <- phaseOutputFilename Cmm- liftIO $ doCpp dflags False{-not raw-}+runPhase (RealPhase CmmCpp) input_fn = do+ hsc_env <- getPipeSession+ output_fn <- phaseOutputFilename Cmm+ liftIO $ doCpp (hsc_dflags hsc_env) (hsc_unit_env hsc_env)+ False{-not raw-} input_fn output_fn return (RealPhase Cmm, output_fn) -runPhase (RealPhase Cmm) input_fn dflags- = do let next_phase = hscPostBackendPhase HsSrcFile (backend dflags)+runPhase (RealPhase Cmm) input_fn = do+ hsc_env <- getPipeSession+ let dflags = hsc_dflags hsc_env+ let next_phase = hscPostBackendPhase HsSrcFile (backend dflags) output_fn <- phaseOutputFilename next_phase PipeState{hsc_env} <- getPipeState liftIO $ hscCompileCmmFile hsc_env input_fn output_fn@@ -1351,12 +1383,15 @@ ----------------------------------------------------------------------------- -- Cc phase -runPhase (RealPhase cc_phase) input_fn dflags+runPhase (RealPhase cc_phase) input_fn | any (cc_phase `eqPhase`) [Cc, Ccxx, HCc, Cobjc, Cobjcxx] = do- let platform = targetPlatform dflags- hcc = cc_phase `eqPhase` HCc- home_unit = mkHomeUnitFromFlags dflags+ hsc_env <- getPipeSession+ let dflags = hsc_dflags hsc_env+ let unit_env = hsc_unit_env hsc_env+ let home_unit = hsc_home_unit hsc_env+ let platform = ue_platform unit_env+ let hcc = cc_phase `eqPhase` HCc let cmdline_include_paths = includePaths dflags @@ -1366,11 +1401,8 @@ -- add package include paths even if we're just compiling .c -- files; this is the Value Add(TM) that using ghc instead of -- gcc gives you :)- pkg_include_dirs <- liftIO $ getUnitIncludePath- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- home_unit- pkgs+ ps <- liftIO $ mayThrowUnitErr (preloadUnitsInfo' unit_env pkgs)+ let pkg_include_dirs = collectIncludeDirs ps let include_paths_global = foldr (\ x xs -> ("-I" ++ x) : xs) [] (includePathsGlobal cmdline_include_paths ++ pkg_include_dirs) let include_paths_quote = foldr (\ x xs -> ("-iquote" ++ x) : xs) []@@ -1395,26 +1427,17 @@ -- cc-options are not passed when compiling .hc files. Our -- hc code doesn't not #include any header files anyway, so these -- options aren't necessary.- pkg_extra_cc_opts <- liftIO $- if hcc- then return []- else getUnitExtraCcOpts- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- home_unit- pkgs+ let pkg_extra_cc_opts+ | hcc = []+ | otherwise = collectExtraCcOpts ps - framework_paths <-- if platformUsesFrameworks platform- then do pkgFrameworkPaths <- liftIO $ getUnitFrameworkPath- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- home_unit- pkgs- let cmdlineFrameworkPaths = frameworkPaths dflags- return $ map ("-F"++)- (cmdlineFrameworkPaths ++ pkgFrameworkPaths)- else return []+ let framework_paths+ | platformUsesFrameworks platform+ = let pkgFrameworkPaths = collectFrameworksDirs ps+ cmdlineFrameworkPaths = frameworkPaths dflags+ in map ("-F"++) (cmdlineFrameworkPaths ++ pkgFrameworkPaths)+ | otherwise+ = [] let cc_opt | optLevel dflags >= 2 = [ "-O2" ] | optLevel dflags >= 1 = [ "-O" ]@@ -1441,7 +1464,7 @@ -- very weakly typed, being derived from C--. ["-fno-strict-aliasing"] - ghcVersionH <- liftIO $ getGhcVersionPathName dflags+ ghcVersionH <- liftIO $ getGhcVersionPathName dflags unit_env liftIO $ GHC.SysTools.runCc (phaseForeignLanguage cc_phase) dflags ( [ GHC.SysTools.FileOption "" input_fn@@ -1496,14 +1519,20 @@ -- As, SpitAs phase : Assembler -- This is for calling the assembler on a regular assembly file-runPhase (RealPhase (As with_cpp)) input_fn dflags+runPhase (RealPhase (As with_cpp)) input_fn = do+ hsc_env <- getPipeSession+ let dflags = hsc_dflags hsc_env+ let unit_env = hsc_unit_env hsc_env+ let platform = ue_platform unit_env+ -- LLVM from version 3.0 onwards doesn't support the OS X system -- assembler, so we use clang as the assembler instead. (#5636)- let as_prog | backend dflags == LLVM &&- platformOS (targetPlatform dflags) == OSDarwin+ let as_prog | backend dflags == LLVM+ , platformOS platform == OSDarwin = GHC.SysTools.runClang- | otherwise = GHC.SysTools.runAs+ | otherwise+ = GHC.SysTools.runAs let cmdline_include_paths = includePaths dflags let pic_c_flags = picCCOpts dflags@@ -1565,20 +1594,9 @@ ----------------------------------------------------------------------------- -- LlvmOpt phase-runPhase (RealPhase LlvmOpt) input_fn dflags- = do- output_fn <- phaseOutputFilename LlvmLlc-- liftIO $ GHC.SysTools.runLlvmOpt dflags- ( optFlag- ++ defaultOptions ++- [ GHC.SysTools.FileOption "" input_fn- , GHC.SysTools.Option "-o"- , GHC.SysTools.FileOption "" output_fn]- )-- return (RealPhase LlvmLlc, output_fn)- where+runPhase (RealPhase LlvmOpt) input_fn = do+ hsc_env <- getPipeSession+ let dflags = hsc_dflags hsc_env -- we always (unless -optlo specified) run Opt since we rely on it to -- fix up some pretty big deficiencies in the code we generate optIdx = max 0 $ min 2 $ optLevel dflags -- ensure we're in [0,2]@@ -1587,6 +1605,8 @@ Nothing -> panic ("runPhase LlvmOpt: llvm-passes file " ++ "is missing passes for level " ++ show optIdx)+ defaultOptions = map GHC.SysTools.Option . concat . fmap words . fst+ $ unzip (llvmOptions dflags) -- don't specify anything if user has specified commands. We do this -- for opt but not llc since opt is very specifically for optimisation@@ -1596,31 +1616,23 @@ then map GHC.SysTools.Option $ words llvmOpts else [] - defaultOptions = map GHC.SysTools.Option . concat . fmap words . fst- $ unzip (llvmOptions dflags)+ output_fn <- phaseOutputFilename LlvmLlc --------------------------------------------------------------------------------- LlvmLlc phase+ liftIO $ GHC.SysTools.runLlvmOpt dflags+ ( optFlag+ ++ defaultOptions +++ [ GHC.SysTools.FileOption "" input_fn+ , GHC.SysTools.Option "-o"+ , GHC.SysTools.FileOption "" output_fn]+ ) -runPhase (RealPhase LlvmLlc) input_fn dflags- = do- next_phase <- if -- hidden debugging flag '-dno-llvm-mangler' to skip mangling- | gopt Opt_NoLlvmMangler dflags -> return (As False)- | otherwise -> return LlvmMangle+ return (RealPhase LlvmLlc, output_fn) - output_fn <- phaseOutputFilename next_phase - liftIO $ GHC.SysTools.runLlvmLlc dflags- ( optFlag- ++ defaultOptions- ++ [ GHC.SysTools.FileOption "" input_fn- , GHC.SysTools.Option "-o"- , GHC.SysTools.FileOption "" output_fn- ]- )+-----------------------------------------------------------------------------+-- LlvmLlc phase - return (RealPhase next_phase, output_fn)- where+runPhase (RealPhase LlvmLlc) input_fn = do -- Note [Clamping of llc optimizations] -- -- See #13724@@ -1660,45 +1672,64 @@ -- -- Observed at least with -mtriple=arm-unknown-linux-gnueabihf -enable-tbaa --- llvmOpts = case optLevel dflags of- 0 -> "-O1" -- required to get the non-naive reg allocator. Passing -regalloc=greedy is not sufficient.- 1 -> "-O1"- _ -> "-O2"+ dflags <- hsc_dflags <$> getPipeSession+ let+ llvmOpts = case optLevel dflags of+ 0 -> "-O1" -- required to get the non-naive reg allocator. Passing -regalloc=greedy is not sufficient.+ 1 -> "-O1"+ _ -> "-O2" - optFlag = if null (getOpts dflags opt_lc)- then map GHC.SysTools.Option $ words llvmOpts- else []+ defaultOptions = map GHC.SysTools.Option . concatMap words . snd+ $ unzip (llvmOptions dflags)+ optFlag = if null (getOpts dflags opt_lc)+ then map GHC.SysTools.Option $ words llvmOpts+ else [] - defaultOptions = map GHC.SysTools.Option . concatMap words . snd- $ unzip (llvmOptions dflags)+ next_phase <- if -- hidden debugging flag '-dno-llvm-mangler' to skip mangling+ | gopt Opt_NoLlvmMangler dflags -> return (As False)+ | otherwise -> return LlvmMangle + output_fn <- phaseOutputFilename next_phase + liftIO $ GHC.SysTools.runLlvmLlc dflags+ ( optFlag+ ++ defaultOptions+ ++ [ GHC.SysTools.FileOption "" input_fn+ , GHC.SysTools.Option "-o"+ , GHC.SysTools.FileOption "" output_fn+ ]+ )++ return (RealPhase next_phase, output_fn)+++ ----------------------------------------------------------------------------- -- LlvmMangle phase -runPhase (RealPhase LlvmMangle) input_fn dflags- = do+runPhase (RealPhase LlvmMangle) input_fn = do let next_phase = As False output_fn <- phaseOutputFilename next_phase+ dflags <- hsc_dflags <$> getPipeSession liftIO $ llvmFixupAsm dflags input_fn output_fn return (RealPhase next_phase, output_fn) ----------------------------------------------------------------------------- -- merge in stub objects -runPhase (RealPhase MergeForeign) input_fn dflags- = do+runPhase (RealPhase MergeForeign) input_fn = do PipeState{foreign_os} <- getPipeState output_fn <- phaseOutputFilename StopLn liftIO $ createDirectoryIfMissing True (takeDirectory output_fn) if null foreign_os then panic "runPhase(MergeForeign): no foreign objects" else do+ dflags <- hsc_dflags <$> getPipeSession liftIO $ joinObjectFiles dflags (input_fn : foreign_os) output_fn return (RealPhase StopLn, output_fn) -- warning suppression-runPhase (RealPhase other) _input_fn _dflags =+runPhase (RealPhase other) _input_fn = panic ("runPhase: don't know how to run phase " ++ show other) maybeMergeForeign :: CompPipeline Phase@@ -1769,30 +1800,29 @@ return [] -linkDynLibCheck :: DynFlags -> [String] -> [UnitId] -> IO ()-linkDynLibCheck dflags o_files dep_units = do+linkDynLibCheck :: DynFlags -> UnitEnv -> [String] -> [UnitId] -> IO ()+linkDynLibCheck dflags unit_env o_files dep_units = do when (haveRtsOptsFlags dflags) $ putLogMsg dflags NoReason SevInfo noSrcSpan $ withPprStyle defaultUserStyle (text "Warning: -rtsopts and -with-rtsopts have no effect with -shared." $$ text " Call hs_init_ghc() from your main() function to set these options.")- linkDynLib dflags o_files dep_units+ linkDynLib dflags unit_env o_files dep_units -- ----------------------------------------------------------------------------- -- Running CPP -doCpp :: DynFlags -> Bool -> FilePath -> FilePath -> IO ()-doCpp dflags raw input_fn output_fn = do+-- | Run CPP+--+-- UnitState is needed to compute MIN_VERSION macros+doCpp :: DynFlags -> UnitEnv -> Bool -> FilePath -> FilePath -> IO ()+doCpp dflags unit_env raw input_fn output_fn = do let hscpp_opts = picPOpts dflags let cmdline_include_paths = includePaths dflags- let home_unit = mkHomeUnitFromFlags dflags-- pkg_include_dirs <- getUnitIncludePath- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- home_unit- []+ let unit_state = ue_units unit_env+ pkg_include_dirs <- mayThrowUnitErr+ (collectIncludeDirs <$> preloadUnitsInfo unit_env) let include_paths_global = foldr (\ x xs -> ("-I" ++ x) : xs) [] (includePathsGlobal cmdline_include_paths ++ pkg_include_dirs) let include_paths_quote = foldr (\ x xs -> ("-iquote" ++ x) : xs) []@@ -1837,13 +1867,12 @@ let th_defs = [ "-D__GLASGOW_HASKELL_TH__" ] -- Default CPP defines in Haskell source- ghcVersionH <- getGhcVersionPathName dflags+ ghcVersionH <- getGhcVersionPathName dflags unit_env let hsSourceCppOpts = [ "-include", ghcVersionH ] -- MIN_VERSION macros- let state = unitState dflags- uids = explicitUnits state- pkgs = catMaybes (map (lookupUnit state) uids)+ let uids = explicitUnits unit_state+ pkgs = catMaybes (map (lookupUnit unit_state) uids) mb_macro_include <- if not (null pkgs) && gopt Opt_VersionMacros dflags then do macro_stub <- newTempName dflags TFL_CurrentModule "h"@@ -2053,16 +2082,13 @@ GHC.SysTools.touch dflags "Touching object file" path -- | Find out path to @ghcversion.h@ file-getGhcVersionPathName :: DynFlags -> IO FilePath-getGhcVersionPathName dflags = do+getGhcVersionPathName :: DynFlags -> UnitEnv -> IO FilePath+getGhcVersionPathName dflags unit_env = do candidates <- case ghcVersionFile dflags of Just path -> return [path]- Nothing -> (map (</> "ghcversion.h")) <$>- (getUnitIncludePath- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- (mkHomeUnitFromFlags dflags)- [rtsUnitId])+ Nothing -> do+ ps <- mayThrowUnitErr (preloadUnitsInfo' unit_env [rtsUnitId])+ return ((</> "ghcversion.h") <$> collectIncludeDirs ps) found <- filterM doesFileExist candidates case found of
compiler/GHC/HsToCore.hs view
@@ -136,11 +136,7 @@ }) = do { let dflags = hsc_dflags hsc_env- home_unit = hsc_home_unit hsc_env- print_unqual = mkPrintUnqualified- (unitState dflags)- home_unit- rdr_env+ print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) rdr_env ; withTiming dflags (text "Desugar"<+>brackets (ppr mod)) (const ()) $
compiler/GHC/HsToCore/Binds.hs view
@@ -18,7 +18,7 @@ module GHC.HsToCore.Binds ( dsTopLHsBinds, dsLHsBinds, decomposeRuleLhs, dsSpec- , dsHsWrapper, dsTcEvBinds, dsTcEvBinds_s, dsEvBinds, dsMkUserRule+ , dsHsWrapper, dsEvTerm, dsTcEvBinds, dsTcEvBinds_s, dsEvBinds, dsMkUserRule ) where
compiler/GHC/HsToCore/Coverage.hs view
@@ -511,7 +511,7 @@ addTickHsExpr :: HsExpr GhcTc -> TM (HsExpr GhcTc) addTickHsExpr e@(HsVar _ (L _ id)) = do freeVar id; return e-addTickHsExpr e@(HsUnboundVar id _) = do freeVar id; return e+addTickHsExpr e@(HsUnboundVar {}) = return e addTickHsExpr e@(HsRecFld _ (Ambiguous id _)) = do freeVar id; return e addTickHsExpr e@(HsRecFld _ (Unambiguous id _)) = do freeVar id; return e addTickHsExpr e@(HsConLikeOut _ con)
compiler/GHC/HsToCore/Docs.hs view
@@ -220,7 +220,7 @@ h98ConArgDocs :: HsConDeclH98Details GhcRn -> Map Int HsDocString h98ConArgDocs con_args = case con_args of- PrefixCon args -> con_arg_docs 0 $ map (unLoc . hsScaledThing) args+ PrefixCon _ args -> con_arg_docs 0 $ map (unLoc . hsScaledThing) args InfixCon arg1 arg2 -> con_arg_docs 0 [ unLoc (hsScaledThing arg1) , unLoc (hsScaledThing arg2) ] RecCon _ -> M.empty
compiler/GHC/HsToCore/Expr.hs view
@@ -268,7 +268,8 @@ dsExpr (HsVar _ (L _ id)) = dsHsVar id dsExpr (HsRecFld _ (Unambiguous id _)) = dsHsVar id dsExpr (HsRecFld _ (Ambiguous id _)) = dsHsVar id-dsExpr (HsUnboundVar id _) = dsHsVar id+dsExpr (HsUnboundVar (HER ref _ _) _) = dsEvTerm =<< readMutVar ref+ -- See Note [Holes] in GHC.Tc.Types.Constraint dsExpr (HsPar _ e) = dsLExpr e dsExpr (ExprWithTySig _ e _) = dsLExpr e@@ -822,7 +823,7 @@ req_wrap = dict_req_wrap <.> mkWpTyApps in_inst_tys pat = noLoc $ ConPat { pat_con = noLoc con- , pat_args = PrefixCon $ map nlVarPat arg_ids+ , pat_args = PrefixCon [] $ map nlVarPat arg_ids , pat_con_ext = ConPatTc { cpt_tvs = ex_tvs , cpt_dicts = eqs_vars ++ theta_vars
compiler/GHC/HsToCore/Foreign/Call.hs view
@@ -350,7 +350,8 @@ -- Data types with a single constructor, which has a single arg -- This includes types like Ptr and ForeignPtr | Just (tycon, tycon_arg_tys) <- maybe_tc_app- , Just data_con <- isDataProductTyCon_maybe tycon -- One constructor, no existentials+ , Just data_con <- tyConSingleAlgDataCon_maybe tycon -- One constructor+ , null (dataConExTyCoVars data_con) -- no existentials , [Scaled _ unwrapped_res_ty] <- dataConInstOrigArgTys data_con tycon_arg_tys -- One argument = do { (maybe_ty, wrapper) <- resultWrapper unwrapped_res_ty ; let marshal_con e = Var (dataConWrapId data_con)
compiler/GHC/HsToCore/Match.hs view
@@ -573,9 +573,9 @@ -> HsConPatDetails GhcTc -> HsConPatDetails GhcTc -- See Note [Bang patterns and newtypes] -- We are transforming !(N p) into (N !p)-push_bang_into_newtype_arg l _ty (PrefixCon (arg:args))+push_bang_into_newtype_arg l _ty (PrefixCon ts (arg:args)) = ASSERT( null args)- PrefixCon [L l (BangPat noExtField arg)]+ PrefixCon ts [L l (BangPat noExtField arg)] push_bang_into_newtype_arg l _ty (RecCon rf) | HsRecFields { rec_flds = L lf fld : flds } <- rf , HsRecField { hsRecFieldArg = arg } <- fld@@ -584,7 +584,7 @@ = L l (BangPat noExtField arg) })] }) push_bang_into_newtype_arg l ty (RecCon rf) -- If a user writes !(T {}) | HsRecFields { rec_flds = [] } <- rf- = PrefixCon [L l (BangPat noExtField (noLoc (WildPat ty)))]+ = PrefixCon [] [L l (BangPat noExtField (noLoc (WildPat ty)))] push_bang_into_newtype_arg _ _ cd = pprPanic "push_bang_into_newtype_arg" (pprConArgs cd)
compiler/GHC/HsToCore/Match/Constructor.hs view
@@ -248,7 +248,7 @@ selectConMatchVars :: [Scaled Type] -> ConArgPats -> DsM [Id] selectConMatchVars arg_tys con = case con of (RecCon {}) -> newSysLocalsDsNoLP arg_tys- (PrefixCon ps) -> selectMatchVars (zipMults arg_tys ps)+ (PrefixCon _ ps) -> selectMatchVars (zipMults arg_tys ps) (InfixCon p1 p2) -> selectMatchVars (zipMults arg_tys [p1, p2]) where zipMults = zipWithEqual "selectConMatchVar" (\a b -> (scaledMult a, unLoc b))@@ -258,7 +258,7 @@ -- are probably never looked at anyway -> ConArgPats -> [Pat GhcTc]-conArgPats _arg_tys (PrefixCon ps) = map unLoc ps+conArgPats _arg_tys (PrefixCon _ ps) = map unLoc ps conArgPats _arg_tys (InfixCon p1 p2) = [unLoc p1, unLoc p2] conArgPats arg_tys (RecCon (HsRecFields { rec_flds = rpats })) | null rpats = map WildPat (map scaledThing arg_tys)
compiler/GHC/HsToCore/Monad.hs view
@@ -86,11 +86,10 @@ import GHC.Data.Bag import GHC.Data.FastString +import GHC.Unit.Env import GHC.Unit.External import GHC.Unit.Module import GHC.Unit.Module.ModGuts-import GHC.Unit.Home-import GHC.Unit.State import GHC.Types.Name.Reader import GHC.Types.Basic ( Origin )@@ -229,9 +228,7 @@ mkDsEnvsFromTcGbl hsc_env msg_var tcg_env = do { cc_st_var <- liftIO $ newIORef newCostCentreState ; eps <- liftIO $ hscEPS hsc_env- ; let dflags = hsc_dflags hsc_env- home_unit = hsc_home_unit hsc_env- unit_state = unitState dflags+ ; let unit_env = hsc_unit_env hsc_env this_mod = tcg_mod tcg_env type_env = tcg_type_env tcg_env rdr_env = tcg_rdr_env tcg_env@@ -239,7 +236,7 @@ complete_matches = hptCompleteSigs hsc_env -- from the home package ++ tcg_complete_matches tcg_env -- from the current module ++ eps_complete_matches eps -- from imports- ; return $ mkDsEnvs unit_state home_unit this_mod rdr_env type_env fam_inst_env+ ; return $ mkDsEnvs unit_env this_mod rdr_env type_env fam_inst_env msg_var cc_st_var complete_matches } @@ -262,9 +259,7 @@ = do { cc_st_var <- newIORef newCostCentreState ; msg_var <- newIORef emptyMessages ; eps <- liftIO $ hscEPS hsc_env- ; let dflags = hsc_dflags hsc_env- home_unit = hsc_home_unit hsc_env- unit_state = unitState dflags+ ; let unit_env = hsc_unit_env hsc_env type_env = typeEnvFromEntities ids (mg_tcs guts) (mg_fam_insts guts) rdr_env = mg_rdr_env guts fam_inst_env = mg_fam_inst_env guts@@ -277,7 +272,7 @@ bindsToIds (Rec binds) = map fst binds ids = concatMap bindsToIds (mg_binds guts) - envs = mkDsEnvs unit_state home_unit this_mod rdr_env type_env+ envs = mkDsEnvs unit_env this_mod rdr_env type_env fam_inst_env msg_var cc_st_var complete_matches ; runDs hsc_env envs thing_inside@@ -298,18 +293,25 @@ ; hsc_env <- getTopEnv ; let DsGblEnv { ds_mod = mod- , ds_fam_inst_env = fam_inst_env } = gbl+ , ds_fam_inst_env = fam_inst_env+ , ds_gbl_rdr_env = rdr_env } = gbl+ -- This is *the* use of ds_gbl_rdr_env:+ -- Make sure the solver (used by the pattern-match overlap checker) has+ -- access to the GlobalRdrEnv and FamInstEnv for the module, so that it+ -- knows how to reduce type families, and which newtypes it can unwrap. + DsLclEnv { dsl_loc = loc } = lcl ; liftIO $ initTc hsc_env HsSrcFile False mod loc $- updGblEnv (\tc_gbl -> tc_gbl { tcg_fam_inst_env = fam_inst_env }) $+ updGblEnv (\tc_gbl -> tc_gbl { tcg_fam_inst_env = fam_inst_env+ , tcg_rdr_env = rdr_env }) $ thing_inside } -mkDsEnvs :: UnitState -> HomeUnit -> Module -> GlobalRdrEnv -> TypeEnv -> FamInstEnv+mkDsEnvs :: UnitEnv -> Module -> GlobalRdrEnv -> TypeEnv -> FamInstEnv -> IORef Messages -> IORef CostCentreState -> CompleteMatches -> (DsGblEnv, DsLclEnv)-mkDsEnvs unit_state home_unit mod rdr_env type_env fam_inst_env msg_var cc_st_var+mkDsEnvs unit_env mod rdr_env type_env fam_inst_env msg_var cc_st_var complete_matches = let if_genv = IfGblEnv { if_doc = text "mkDsEnvs", if_rec_types = Just (mod, return type_env) }@@ -318,8 +320,9 @@ real_span = realSrcLocSpan (mkRealSrcLoc (moduleNameFS (moduleName mod)) 1 1) gbl_env = DsGblEnv { ds_mod = mod , ds_fam_inst_env = fam_inst_env+ , ds_gbl_rdr_env = rdr_env , ds_if_env = (if_genv, if_lenv)- , ds_unqual = mkPrintUnqualified unit_state home_unit rdr_env+ , ds_unqual = mkPrintUnqualified unit_env rdr_env , ds_msgs = msg_var , ds_complete_matches = complete_matches , ds_cc_st = cc_st_var
compiler/GHC/HsToCore/Pmc/Desugar.hs view
@@ -255,7 +255,7 @@ desugarConPatOut :: Id -> ConLike -> [Type] -> [TyVar] -> [EvVar] -> HsConPatDetails GhcTc -> DsM [PmGrd] desugarConPatOut x con univ_tys ex_tvs dicts = \case- PrefixCon ps -> go_field_pats (zip [0..] ps)+ PrefixCon _ ps -> go_field_pats (zip [0..] ps) InfixCon p1 p2 -> go_field_pats (zip [0..] [p1,p2]) RecCon (HsRecFields fs _) -> go_field_pats (rec_field_ps fs) where
compiler/GHC/HsToCore/Pmc/Solver.hs view
@@ -58,7 +58,7 @@ import GHC.Types.Var.Set import GHC.Core import GHC.Core.FVs (exprFreeVars)-import GHC.Core.Map+import GHC.Core.Map.Expr import GHC.Core.SimpleOpt (simpleOptExpr, exprIsConApp_maybe) import GHC.Core.Utils (exprType) import GHC.Core.Make (mkListExpr, mkCharExpr)
compiler/GHC/HsToCore/Pmc/Solver/Types.hs view
@@ -54,7 +54,7 @@ import GHC.Core.TyCon import GHC.Types.Literal import GHC.Core-import GHC.Core.Map+import GHC.Core.Map.Expr import GHC.Core.Utils (exprType) import GHC.Builtin.Names import GHC.Builtin.Types
compiler/GHC/HsToCore/Quote.hs view
@@ -283,7 +283,7 @@ , hs_docs = docs }) = do { let { bndrs = hsScopedTvBinders valds ++ hsGroupBinders group- ++ hsPatSynSelectors valds+ ++ map extFieldOcc (hsPatSynSelectors valds) ; instds = tyclds >>= group_instds } ; ss <- mkGenSyms bndrs ; @@ -1884,11 +1884,11 @@ -- their pattern-only bound right hand sides have different names, -- we want to treat them the same in TH. This is the reason why we -- need an adjusted mkGenArgSyms in the `RecCon` case below.- mkGenArgSyms (PrefixCon args) = mkGenSyms (map unLoc args)+ mkGenArgSyms (PrefixCon _ args) = mkGenSyms (map unLoc args) mkGenArgSyms (InfixCon arg1 arg2) = mkGenSyms [unLoc arg1, unLoc arg2] mkGenArgSyms (RecCon fields) = do { let pats = map (unLoc . recordPatSynPatVar) fields- sels = map (unLoc . recordPatSynSelectorId) fields+ sels = map (extFieldOcc . recordPatSynField) fields ; ss <- mkGenSyms sels ; return $ replaceNames (zip sels pats) ss } @@ -1910,7 +1910,7 @@ = rep2 patSynDName [syn, args, dir, pat] repPatSynArgs :: HsPatSynDetails GhcRn -> MetaM (Core (M TH.PatSynArgs))-repPatSynArgs (PrefixCon args)+repPatSynArgs (PrefixCon _ args) = do { args' <- repList nameTyConName lookupLOcc args ; repPrefixPatSynArgs args' } repPatSynArgs (InfixCon arg1 arg2)@@ -1918,9 +1918,9 @@ ; arg2' <- lookupLOcc arg2 ; repInfixPatSynArgs arg1' arg2' } repPatSynArgs (RecCon fields)- = do { sels' <- repList nameTyConName lookupLOcc sels+ = do { sels' <- repList nameTyConName (lookupOcc . extFieldOcc) sels ; repRecordPatSynArgs sels' }- where sels = map recordPatSynSelectorId fields+ where sels = map recordPatSynField fields repPrefixPatSynArgs :: Core [TH.Name] -> MetaM (Core (M TH.PatSynArgs)) repPrefixPatSynArgs (MkC nms) = rep2 prefixPatSynName [nms]@@ -2016,7 +2016,9 @@ repP (ConPat NoExtField dc details) = do { con_str <- lookupLOcc dc ; case details of- PrefixCon ps -> do { qs <- repLPs ps; repPcon con_str qs }+ PrefixCon tyargs ps -> do { qs <- repLPs ps+ ; ts <- repListM typeTyConName (repTy . unLoc . hsps_body) tyargs+ ; repPcon con_str ts qs } RecCon rec -> do { fps <- repListM fieldPatTyConName rep_fld (rec_flds rec) ; repPrec con_str fps } InfixCon p1 p2 -> do { p1' <- repLP p1;@@ -2028,7 +2030,6 @@ rep_fld (L _ fld) = do { MkC v <- lookupLOcc (hsRecFieldSel fld) ; MkC p <- repLP (hsRecFieldArg fld) ; rep2 fieldPatName [v,p] }- 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' }@@ -2249,8 +2250,8 @@ , mkIntExprInt platform alt , mkIntExprInt platform arity ] } -repPcon :: Core TH.Name -> Core [(M TH.Pat)] -> MetaM (Core (M TH.Pat))-repPcon (MkC s) (MkC ps) = rep2 conPName [s, ps]+repPcon :: Core TH.Name -> Core [(M TH.Type)] -> Core [(M TH.Pat)] -> MetaM (Core (M TH.Pat))+repPcon (MkC s) (MkC ts) (MkC ps) = rep2 conPName [s, ts, ps] repPrec :: Core TH.Name -> Core [M (TH.Name, TH.Pat)] -> MetaM (Core (M TH.Pat)) repPrec (MkC c) (MkC rps) = rep2 recPName [c,rps]@@ -2621,7 +2622,7 @@ repH98DataCon con details = do con' <- lookupLOcc con -- See Note [Binders and occurrences] case details of- PrefixCon ps -> do+ PrefixCon _ ps -> do arg_tys <- repPrefixConArgs ps rep2 normalCName [unC con', unC arg_tys] InfixCon st1 st2 -> do
compiler/GHC/HsToCore/Types.hs view
@@ -12,6 +12,7 @@ import GHC.Types.Name.Env import GHC.Types.SrcLoc import GHC.Types.Var+import GHC.Types.Name.Reader (GlobalRdrEnv) import GHC.Hs (LForeignDecl, HsExpr, GhcTc) import GHC.Tc.Types (TcRnIf, IfGblEnv, IfLclEnv, CompleteMatches) import GHC.HsToCore.Pmc.Types (Nablas)@@ -42,6 +43,9 @@ = DsGblEnv { ds_mod :: Module -- For SCC profiling , ds_fam_inst_env :: FamInstEnv -- Like tcg_fam_inst_env+ , ds_gbl_rdr_env :: GlobalRdrEnv -- needed *only* to know what newtype+ -- constructors are in scope during+ -- pattern-match satisfiability checking , ds_unqual :: PrintUnqualified , ds_msgs :: IORef Messages -- Warning messages , ds_if_env :: (IfGblEnv, IfLclEnv) -- Used for looking up global,
compiler/GHC/HsToCore/Usage.hs view
@@ -37,8 +37,6 @@ import GHC.Unit.Module.ModIface import GHC.Unit.Module.Deps -import GHC.Linker.Unit- import GHC.Data.Maybe import Control.Monad (filterM)@@ -186,12 +184,12 @@ LookupFound _ pkg -> do -- The plugin is from an external package: -- search for the library files containing the plugin.- let searchPaths = collectLibraryPaths (ways dflags) [pkg]+ let searchPaths = collectLibraryDirs (ways dflags) [pkg] useDyn = WayDyn `elem` ways dflags suffix = if useDyn then platformSOExt platform else "a" libLocs = [ searchPath </> "lib" ++ libLoc <.> suffix | searchPath <- searchPaths- , libLoc <- packageHsLibs dflags pkg+ , libLoc <- unitHsLibs (ghcNameVersion dflags) (ways dflags) pkg ] -- we also try to find plugin library files by adding WayDyn way, -- if it isn't already present (see trac #15492)@@ -202,7 +200,7 @@ let dflags' = dflags { targetWays_ = addWay WayDyn (targetWays_ dflags) } dlibLocs = [ searchPath </> platformHsSOName platform dlibLoc | searchPath <- searchPaths- , dlibLoc <- packageHsLibs dflags' pkg+ , dlibLoc <- unitHsLibs (ghcNameVersion dflags') (ways dflags') pkg ] in libLocs ++ dlibLocs files <- filterM doesFileExist paths@@ -228,7 +226,7 @@ where dflags = hsc_dflags hsc_env platform = targetPlatform dflags- pkgs = unitState dflags+ pkgs = hsc_units hsc_env pNm = moduleName $ mi_module pluginModule pPkg = moduleUnit $ mi_module pluginModule deps = map gwib_mod $
compiler/GHC/HsToCore/Utils.hs view
@@ -494,6 +494,13 @@ -> v1 -- Note [Desugaring seq], points (2) and (3) _ -> mkWildValBinder Many ty1 +mkCoreAppDs _ (Var f `App` Type _r) arg+ | f `hasKey` noinlineIdKey -- See Note [noinlineId magic] in GHC.Types.Id.Make+ , (fun, args) <- collectArgs arg+ , not (null args)+ = (Var f `App` Type (exprType fun) `App` fun)+ `mkCoreApps` args+ mkCoreAppDs s fun arg = mkCoreApp s fun arg -- The rest is done in GHC.Core.Make -- NB: No argument can be levity polymorphic@@ -737,7 +744,7 @@ is_flat_prod_pat (ConPat { pat_con = L _ pcon , pat_args = ps}) | RealDataCon con <- pcon- , isProductTyCon (dataConTyCon con)+ , Just _ <- tyConSingleDataCon_maybe (dataConTyCon con) = all is_triv_lpat (hsConPatArgs ps) is_flat_prod_pat _ = False
compiler/GHC/Iface/Ext/Ast.hs view
@@ -18,6 +18,8 @@ Main functions for .hie file generation -} +#include "GhclibHsVersions.h"+ module GHC.Iface.Ext.Ast ( mkHieFile, mkHieFileWithSource, getCompressedAsts, enrichHie) where import GHC.Utils.Outputable(ppr)@@ -55,6 +57,7 @@ import GHC.Builtin.Uniques import GHC.Iface.Make ( mkIfaceExports ) import GHC.Utils.Panic+import GHC.Utils.Misc import GHC.Data.Maybe import GHC.Data.FastString @@ -69,7 +72,7 @@ import qualified Data.Map as M import qualified Data.Set as S import Data.Data ( Data, Typeable )-import Data.List ( foldl1' )+import Data.Void ( Void, absurd ) import Control.Monad ( forM_ ) import Control.Monad.Trans.State.Strict import Control.Monad.Trans.Reader@@ -162,7 +165,7 @@ straightforward. If you are extending the GHC AST, you will need to provide a `ToHie` instance for any new types you may have introduced in the AST. -Here are is an extract from the `ToHie` instance for (LHsExpr (GhcPass p)):+Here is an extract from the `ToHie` instance for (LHsExpr (GhcPass p)): toHie e@(L mspan oexpr) = concatM $ getTypeNode e : case oexpr of HsVar _ (L _ var) ->@@ -484,6 +487,18 @@ map (\(RS sc a) -> PS rsp useScope sc a) $ listScopes patScope xs +-- | 'listScopes' specialised to 'HsPatSigType'+tScopes+ :: Scope+ -> Scope+ -> [HsPatSigType (GhcPass a)]+ -> [TScoped (HsPatSigType (GhcPass a))]+tScopes scope rhsScope xs =+ map (\(RS sc a) -> TS (ResolvedScopes [scope, sc]) (unLoc a)) $+ listScopes rhsScope (map (\hsps -> L (getLoc $ hsps_body hsps) hsps) xs)+ -- We make the HsPatSigType into a Located one by using the location of the underlying LHsType.+ -- We then strip off the redundant location information afterward, and take the union of the given scope and those to the right when forming the TS.+ -- | 'listScopes' specialised to 'TVScoped' things tvScopes :: TyVarScope@@ -567,6 +582,9 @@ class HasType a where getTypeNode :: a -> HieM [HieAST Type] +instance ToHie Void where+ toHie v = absurd v+ instance (ToHie a) => ToHie [a] where toHie = concatMapM toHie @@ -707,6 +725,7 @@ HieTc -> -- Some expression forms have their type immediately available let tyOpt = case e' of+ HsUnboundVar (HER _ ty _) _ -> Just ty HsLit _ l -> Just (hsLitType l) HsOverLit _ o -> Just (overLitType o) @@ -746,7 +765,6 @@ skipDesugaring :: HsExpr GhcTc -> Bool skipDesugaring e = case e of HsVar{} -> False- HsUnboundVar{} -> False HsConLikeOut{} -> False HsRecFld{} -> False HsOverLabel{} -> False@@ -773,7 +791,6 @@ , Data (HsTupArg (GhcPass p)) , Data (IPBind (GhcPass p)) , ToHie (Context (Located (IdGhcP p)))- , ToHie (Context (Located (XUnboundVar (GhcPass p)))) , ToHie (RFContext (Located (AmbiguousFieldOcc (GhcPass p)))) , ToHie (RFContext (Located (FieldOcc (GhcPass p)))) , ToHie (TScoped (LHsWcType (GhcPass (NoGhcTcPass p))))@@ -855,15 +872,15 @@ varScope = mkLScope var patScope = mkScope $ getLoc pat detScope = case dets of- (PrefixCon args) -> foldr combineScopes NoScope $ map mkLScope args+ (PrefixCon _ args) -> foldr combineScopes NoScope $ map mkLScope args (InfixCon a b) -> combineScopes (mkLScope a) (mkLScope b) (RecCon r) -> foldr go NoScope r go (RecordPatSynField a b) c = combineScopes c- $ combineScopes (mkLScope a) (mkLScope b)+ $ combineScopes (mkLScope (rdrNameFieldOcc a)) (mkLScope b) detSpan = case detScope of LocalScope a -> Just a _ -> Nothing- toBind (PrefixCon args) = PrefixCon $ map (C Use) args+ toBind (PrefixCon ts args) = ASSERT(null ts) PrefixCon ts $ map (C Use) args toBind (InfixCon a b) = InfixCon (C Use a) (C Use b) toBind (RecCon r) = RecCon $ map (PSC detSpan) r @@ -945,7 +962,7 @@ , toHie $ L ospan wrap , toHie $ map (C (EvidenceVarBind EvPatternBind evscope rsp) . L ospan) ev_vars- ]+ ] ] HieRn -> [ toHie $ C Use con@@ -985,9 +1002,10 @@ HieRn -> [] #endif where- contextify :: a ~ LPat (GhcPass p) => HsConDetails a (HsRecFields (GhcPass p) a)- -> HsConDetails (PScoped a) (RContext (HsRecFields (GhcPass p) (PScoped a)))- contextify (PrefixCon args) = PrefixCon $ patScopes rsp scope pscope args+ contextify :: a ~ LPat (GhcPass p) => HsConDetails (HsPatSigType (NoGhcTc (GhcPass p))) a (HsRecFields (GhcPass p) a)+ -> HsConDetails (TScoped (HsPatSigType (NoGhcTc (GhcPass p)))) (PScoped a) (RContext (HsRecFields (GhcPass p) (PScoped a)))+ contextify (PrefixCon tyargs args) = PrefixCon (tScopes scope argscope tyargs) (patScopes rsp scope pscope args)+ where argscope = foldr combineScopes NoScope $ map mkLScope args contextify (InfixCon a b) = InfixCon a' b' where [a', b'] = patScopes rsp scope pscope [a,b] contextify (RecCon r) = RecCon $ RC RecFieldMatch $ contextify_rec r@@ -1034,8 +1052,7 @@ [ toHie $ C Use (L mspan var) -- Patch up var location since typechecker removes it ]- HsUnboundVar var _ ->- [ toHie $ C Use (L mspan var) ]+ HsUnboundVar _ _ -> [] -- there is an unbound name here, but that causes trouble HsConLikeOut _ con -> [ toHie $ C Use $ L mspan $ conLikeName con ]@@ -1303,8 +1320,8 @@ , toHie $ PS Nothing sc NoScope pat ] -instance (ToHie arg, ToHie rec) => ToHie (HsConDetails arg rec) where- toHie (PrefixCon args) = toHie args+instance (ToHie tyarg, ToHie arg, ToHie rec) => ToHie (HsConDetails tyarg arg rec) where+ toHie (PrefixCon tyargs args) = concatM [ toHie tyargs, toHie args ] toHie (RecCon rec) = toHie rec toHie (InfixCon a b) = concatM [ toHie a, toHie b] @@ -1554,9 +1571,9 @@ rhsScope = combineScopes ctxScope argsScope ctxScope = maybe NoScope mkLScope ctx argsScope = case dets of- PrefixCon xs -> scaled_args_scope xs- InfixCon a b -> scaled_args_scope [a, b]- RecCon x -> mkLScope x+ PrefixCon _ xs -> scaled_args_scope xs+ InfixCon a b -> scaled_args_scope [a, b]+ RecCon x -> mkLScope x where scaled_args_scope :: [HsScaled GhcRn (LHsType GhcRn)] -> Scope scaled_args_scope = foldr combineScopes NoScope . map (mkLScope . hsScaledThing) @@ -1870,8 +1887,12 @@ instance ToHie (Located (TyFamInstDecl GhcRn)) where toHie (L sp (TyFamInstDecl d)) = toHie $ TS (ResolvedScopes [mkScope sp]) d -instance ToHie (Context a)- => ToHie (PatSynFieldContext (RecordPatSynField a)) where+instance HiePass p => ToHie (Context (FieldOcc (GhcPass p))) where+ toHie (C c (FieldOcc n (L l _))) = case hiePass @p of+ HieTc -> toHie (C c (L l n))+ HieRn -> toHie (C c (L l n))++instance HiePass p => ToHie (PatSynFieldContext (RecordPatSynField (GhcPass p))) where toHie (PSC sp (RecordPatSynField a b)) = concatM $ [ toHie $ C (RecField RecFieldDecl sp) a , toHie $ C Use b@@ -2003,7 +2024,7 @@ IEThingAll _ n -> [ toHie $ IEC c n ]- IEThingWith _ n _ ns flds ->+ IEThingWith flds n _ ns -> [ toHie $ IEC c n , toHie $ map (IEC c) ns , toHie $ map (IEC c) flds@@ -2027,7 +2048,7 @@ [ toHie $ C (IEThing c) n ] -instance ToHie (IEContext (Located (FieldLbl Name))) where+instance ToHie (IEContext (Located FieldLabel)) where toHie (IEC c (L span lbl)) = concatM $ makeNode lbl span : case lbl of FieldLabel _ _ n -> [ toHie $ C (IEThing c) $ L span n
compiler/GHC/Iface/Ext/Utils.hs view
@@ -8,7 +8,7 @@ import GHC.Prelude -import GHC.Core.Map+import GHC.Core.Map.Type import GHC.Driver.Session ( DynFlags ) import GHC.Driver.Ppr import GHC.Data.FastString ( FastString, mkFastString )
compiler/GHC/Iface/Load.hs view
@@ -7,6 +7,7 @@ {-# LANGUAGE CPP, BangPatterns, RecordWildCards, NondecreasingIndentation #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -30,12 +31,16 @@ needWiredInHomeIface, loadWiredInHomeIface, pprModIfaceSimple,- ifaceStats, pprModIface, showIface+ ifaceStats, pprModIface, showIface,++ cannotFindModule ) where #include "GhclibHsVersions.h" import GHC.Prelude+import GHC.Platform.Ways+import GHC.Platform.Profile import {-# SOURCE #-} GHC.IfaceToCore ( tcIfaceDecls, tcIfaceRules, tcIfaceInst, tcIfaceFamInst@@ -87,7 +92,6 @@ import GHC.Types.Unique.FM import GHC.Types.Unique.DSet import GHC.Types.SrcLoc-import GHC.Types.FieldLabel import GHC.Types.TyThing import GHC.Unit.External@@ -99,6 +103,7 @@ import GHC.Unit.Home import GHC.Unit.Home.ModInfo import GHC.Unit.Finder+import GHC.Unit.Env import GHC.Data.Maybe import GHC.Data.FastString@@ -310,7 +315,7 @@ ; case res of Found _ mod -> initIfaceTcRn $ loadInterface doc mod (ImportByUser want_boot) -- TODO: Make sure this error message is good- err -> return (Failed (cannotFindModule (hsc_dflags hsc_env) mod err)) }+ err -> return (Failed (cannotFindModule hsc_env mod err)) } -- | Load interface directly for a fully qualified 'Module'. (This is a fairly -- rare operation, but in particular it is used to load orphan modules@@ -839,7 +844,7 @@ -- Look for the file hsc_env <- getTopEnv mb_found <- liftIO (findExactModule hsc_env mod)- let home_unit = hsc_home_unit hsc_env+ let home_unit = hsc_home_unit hsc_env case mb_found of InstalledFound loc mod -> do -- Found file, so read it@@ -855,20 +860,25 @@ return r err -> do traceIf (text "...not found")- dflags <- getDynFlags- return (Failed (cannotFindInterface dflags- (moduleName mod) err))+ hsc_env <- getTopEnv+ let profile = Profile (targetPlatform dflags) (ways dflags)+ return $ Failed $ cannotFindInterface+ (hsc_unit_env hsc_env)+ profile+ (may_show_locations (hsc_dflags hsc_env))+ (moduleName mod)+ err where read_file file_path = do traceIf (text "readIFace" <+> text file_path) -- Figure out what is recorded in mi_module. If this is -- a fully definite interface, it'll match exactly, but -- if it's indefinite, the inside will be uninstantiated!- dflags <- getDynFlags+ unit_state <- hsc_units <$> getTopEnv let wanted_mod = case getModuleInstantiation wanted_mod_with_insts of (_, Nothing) -> wanted_mod_with_insts (_, Just indef_mod) ->- instModuleToModule (unitState dflags)+ instModuleToModule unit_state (uninstantiateInstantiatedModule indef_mod) read_result <- readIface wanted_mod file_path case read_result of@@ -946,8 +956,8 @@ ********************************************************* -} -initExternalPackageState :: HomeUnit -> ExternalPackageState-initExternalPackageState home_unit+initExternalPackageState :: UnitId -> ExternalPackageState+initExternalPackageState home_unit_id = EPS { eps_is_boot = emptyUFM, eps_PIT = emptyPackageIfaceTable,@@ -966,9 +976,9 @@ } where enableBignumRules- | isHomeUnitInstanceOf home_unit primUnitId = EnableBignumRules False- | isHomeUnitInstanceOf home_unit bignumUnitId = EnableBignumRules False- | otherwise = EnableBignumRules True+ | home_unit_id == primUnitId = EnableBignumRules False+ | home_unit_id == bignumUnitId = EnableBignumRules False+ | otherwise = EnableBignumRules True builtinRules' = builtinRules enableBignumRules {-@@ -1042,7 +1052,7 @@ showIface :: HscEnv -> FilePath -> IO () showIface hsc_env filename = do let dflags = hsc_dflags hsc_env- unit_state = unitState dflags+ unit_state = hsc_units hsc_env printer = putLogMsg dflags NoReason SevOutput noSrcSpan . withPprStyle defaultDumpStyle -- skip the hi way check; we don't want to worry about profiled vs.@@ -1059,17 +1069,21 @@ neverQualifyPackages putLogMsg dflags NoReason SevDump noSrcSpan $ withPprStyle (mkDumpStyle print_unqual)- $ pprWithUnitState unit_state- $ pprModIface iface+ $ pprModIface unit_state iface --- Show a ModIface but don't display details; suitable for ModIfaces stored in+-- | Show a ModIface but don't display details; suitable for ModIfaces stored in -- the EPT.-pprModIfaceSimple :: ModIface -> SDoc-pprModIfaceSimple iface = ppr (mi_module iface) $$ pprDeps (mi_deps iface) $$ nest 2 (vcat (map pprExport (mi_exports iface)))+pprModIfaceSimple :: UnitState -> ModIface -> SDoc+pprModIfaceSimple unit_state iface =+ ppr (mi_module iface)+ $$ pprDeps unit_state (mi_deps iface)+ $$ nest 2 (vcat (map pprExport (mi_exports iface))) -pprModIface :: ModIface -> SDoc--- Show a ModIface-pprModIface iface@ModIface{ mi_final_exts = exts }+-- | Show a ModIface+--+-- The UnitState is used to pretty-print units+pprModIface :: UnitState -> ModIface -> SDoc+pprModIface unit_state iface@ModIface{ mi_final_exts = exts } = vcat [ text "interface" <+> ppr (mi_module iface) <+> pp_hsc_src (mi_hsc_src iface) <+> (if mi_orphan exts then text "[orphan module]" else Outputable.empty)@@ -1089,7 +1103,7 @@ , nest 2 (text "where") , text "exports:" , nest 2 (vcat (map pprExport (mi_exports iface)))- , pprDeps (mi_deps iface)+ , pprDeps unit_state (mi_deps iface) , vcat (map pprUsage (mi_usages iface)) , vcat (map pprIfaceAnnotation (mi_anns iface)) , pprFixities (mi_fixities iface)@@ -1119,16 +1133,17 @@ -} pprExport :: IfaceExport -> SDoc-pprExport (Avail n) = ppr n-pprExport (AvailTC _ [] []) = Outputable.empty-pprExport (AvailTC n ns0 fs)- = case ns0 of- (n':ns) | n==n' -> ppr n <> pp_export ns fs- _ -> ppr n <> vbar <> pp_export ns0 fs+pprExport (Avail n) = ppr n+pprExport (AvailTC _ []) = Outputable.empty+pprExport avail@(AvailTC n _) =+ ppr n <> mark <> pp_export (availSubordinateGreNames avail) where- pp_export [] [] = Outputable.empty- pp_export names fs = braces (hsep (map ppr names ++ map (ppr . flLabel) fs))+ mark | availExportsDecl avail = Outputable.empty+ | otherwise = vbar + pp_export [] = Outputable.empty+ pp_export names = braces (hsep (map ppr names))+ pprUsage :: Usage -> SDoc pprUsage usage@UsagePackageModule{} = pprUsageImport usage usg_mod@@ -1153,10 +1168,12 @@ safe | usg_safe usage = text "safe" | otherwise = text " -/ " -pprDeps :: Dependencies -> SDoc-pprDeps (Deps { dep_mods = mods, dep_pkgs = pkgs, dep_orphs = orphs,- dep_finsts = finsts })- = vcat [text "module dependencies:" <+> fsep (map ppr_mod mods),+-- | Pretty-print unit dependencies+pprDeps :: UnitState -> Dependencies -> SDoc+pprDeps unit_state (Deps { dep_mods = mods, dep_pkgs = pkgs, dep_orphs = orphs,+ dep_finsts = finsts })+ = pprWithUnitState unit_state $+ vcat [text "module dependencies:" <+> fsep (map ppr_mod mods), text "package dependencies:" <+> fsep (map ppr_pkg pkgs), text "orphans:" <+> fsep (map ppr orphs), text "family instance modules:" <+> fsep (map ppr finsts)@@ -1242,3 +1259,268 @@ Just file -> space <> parens (text file) Nothing -> Outputable.empty) <+> text "which is not loaded"+++-- -----------------------------------------------------------------------------+-- Error messages++cannotFindInterface :: UnitEnv -> Profile -> ([FilePath] -> SDoc) -> ModuleName -> InstalledFindResult -> SDoc+cannotFindInterface = cantFindInstalledErr (sLit "Failed to load interface for")+ (sLit "Ambiguous interface for")++cantFindInstalledErr+ :: PtrString+ -> PtrString+ -> UnitEnv+ -> Profile+ -> ([FilePath] -> SDoc)+ -> ModuleName+ -> InstalledFindResult+ -> SDoc+cantFindInstalledErr cannot_find _ unit_env profile tried_these mod_name find_result+ = ptext cannot_find <+> quotes (ppr mod_name)+ $$ more_info+ where+ home_unit = ue_home_unit unit_env+ unit_state = ue_units unit_env+ build_tag = waysBuildTag (profileWays profile)++ more_info+ = case find_result of+ InstalledNoPackage pkg+ -> text "no unit id matching" <+> quotes (ppr pkg) <+>+ text "was found" $$ looks_like_srcpkgid pkg++ InstalledNotFound files mb_pkg+ | Just pkg <- mb_pkg, not (isHomeUnitId home_unit pkg)+ -> not_found_in_package pkg files++ | null files+ -> text "It is not a module in the current program, or in any known package."++ | otherwise+ -> tried_these files++ _ -> panic "cantFindInstalledErr"++ looks_like_srcpkgid :: UnitId -> SDoc+ looks_like_srcpkgid pk+ -- Unsafely coerce a unit id (i.e. an installed package component+ -- identifier) into a PackageId and see if it means anything.+ | (pkg:pkgs) <- searchPackageId unit_state (PackageId (unitIdFS pk))+ = parens (text "This unit ID looks like the source package ID;" $$+ text "the real unit ID is" <+> quotes (ftext (unitIdFS (unitId pkg))) $$+ (if null pkgs then Outputable.empty+ else text "and" <+> int (length pkgs) <+> text "other candidates"))+ -- Todo: also check if it looks like a package name!+ | otherwise = Outputable.empty++ not_found_in_package pkg files+ | build_tag /= ""+ = let+ build = if build_tag == "p" then "profiling"+ else "\"" ++ build_tag ++ "\""+ in+ text "Perhaps you haven't installed the " <> text build <>+ text " libraries for package " <> quotes (ppr pkg) <> char '?' $$+ tried_these files++ | otherwise+ = text "There are files missing in the " <> quotes (ppr pkg) <>+ text " package," $$+ text "try running 'ghc-pkg check'." $$+ tried_these files++may_show_locations :: DynFlags -> [FilePath] -> SDoc+may_show_locations dflags files+ | null files = Outputable.empty+ | verbosity dflags < 3 =+ text "Use -v (or `:set -v` in ghci) " <>+ text "to see a list of the files searched for."+ | otherwise =+ hang (text "Locations searched:") 2 $ vcat (map text files)++cannotFindModule :: HscEnv -> ModuleName -> FindResult -> SDoc+cannotFindModule hsc_env = cannotFindModule'+ (hsc_dflags hsc_env)+ (hsc_unit_env hsc_env)+ (targetProfile (hsc_dflags hsc_env))+++cannotFindModule' :: DynFlags -> UnitEnv -> Profile -> ModuleName -> FindResult -> SDoc+cannotFindModule' dflags unit_env profile mod res = pprWithUnitState (ue_units unit_env) $+ cantFindErr (gopt Opt_BuildingCabalPackage dflags)+ (sLit cannotFindMsg)+ (sLit "Ambiguous module name")+ unit_env+ profile+ (may_show_locations dflags)+ mod+ res+ where+ cannotFindMsg =+ case res of+ NotFound { fr_mods_hidden = hidden_mods+ , fr_pkgs_hidden = hidden_pkgs+ , fr_unusables = unusables }+ | not (null hidden_mods && null hidden_pkgs && null unusables)+ -> "Could not load module"+ _ -> "Could not find module"++cantFindErr+ :: Bool -- ^ Using Cabal?+ -> PtrString+ -> PtrString+ -> UnitEnv+ -> Profile+ -> ([FilePath] -> SDoc)+ -> ModuleName+ -> FindResult+ -> SDoc+cantFindErr _ _ multiple_found _ _ _ mod_name (FoundMultiple mods)+ | Just pkgs <- unambiguousPackages+ = hang (ptext multiple_found <+> quotes (ppr mod_name) <> colon) 2 (+ sep [text "it was found in multiple packages:",+ hsep (map ppr pkgs) ]+ )+ | otherwise+ = hang (ptext multiple_found <+> quotes (ppr mod_name) <> colon) 2 (+ vcat (map pprMod mods)+ )+ where+ unambiguousPackages = foldl' unambiguousPackage (Just []) mods+ unambiguousPackage (Just xs) (m, ModOrigin (Just _) _ _ _)+ = Just (moduleUnit m : xs)+ unambiguousPackage _ _ = Nothing++ pprMod (m, o) = text "it is bound as" <+> ppr m <+>+ text "by" <+> pprOrigin m o+ pprOrigin _ ModHidden = panic "cantFindErr: bound by mod hidden"+ pprOrigin _ (ModUnusable _) = panic "cantFindErr: bound by mod unusable"+ pprOrigin m (ModOrigin e res _ f) = sep $ punctuate comma (+ if e == Just True+ then [text "package" <+> ppr (moduleUnit m)]+ else [] +++ map ((text "a reexport in package" <+>)+ .ppr.mkUnit) res +++ if f then [text "a package flag"] else []+ )++cantFindErr using_cabal cannot_find _ unit_env profile tried_these mod_name find_result+ = ptext cannot_find <+> quotes (ppr mod_name)+ $$ more_info+ where+ home_unit = ue_home_unit unit_env+ more_info+ = case find_result of+ NoPackage pkg+ -> text "no unit id matching" <+> quotes (ppr pkg) <+>+ text "was found"++ NotFound { fr_paths = files, fr_pkg = mb_pkg+ , fr_mods_hidden = mod_hiddens, fr_pkgs_hidden = pkg_hiddens+ , fr_unusables = unusables, fr_suggestions = suggest }+ | Just pkg <- mb_pkg, not (isHomeUnit home_unit pkg)+ -> not_found_in_package pkg files++ | not (null suggest)+ -> pp_suggestions suggest $$ tried_these files++ | null files && null mod_hiddens &&+ null pkg_hiddens && null unusables+ -> text "It is not a module in the current program, or in any known package."++ | otherwise+ -> vcat (map pkg_hidden pkg_hiddens) $$+ vcat (map mod_hidden mod_hiddens) $$+ vcat (map unusable unusables) $$+ tried_these files++ _ -> panic "cantFindErr"++ build_tag = waysBuildTag (profileWays profile)++ not_found_in_package pkg files+ | build_tag /= ""+ = let+ build = if build_tag == "p" then "profiling"+ else "\"" ++ build_tag ++ "\""+ in+ text "Perhaps you haven't installed the " <> text build <>+ text " libraries for package " <> quotes (ppr pkg) <> char '?' $$+ tried_these files++ | otherwise+ = text "There are files missing in the " <> quotes (ppr pkg) <>+ text " package," $$+ text "try running 'ghc-pkg check'." $$+ tried_these files++ pkg_hidden :: Unit -> SDoc+ pkg_hidden uid =+ text "It is a member of the hidden package"+ <+> quotes (ppr uid)+ --FIXME: we don't really want to show the unit id here we should+ -- show the source package id or installed package id if it's ambiguous+ <> dot $$ pkg_hidden_hint uid++ pkg_hidden_hint uid+ | using_cabal+ = let pkg = expectJust "pkg_hidden" (lookupUnit (ue_units unit_env) uid)+ in text "Perhaps you need to add" <+>+ quotes (ppr (unitPackageName pkg)) <+>+ text "to the build-depends in your .cabal file."+ | Just pkg <- lookupUnit (ue_units unit_env) uid+ = text "You can run" <+>+ quotes (text ":set -package " <> ppr (unitPackageName pkg)) <+>+ text "to expose it." $$+ text "(Note: this unloads all the modules in the current scope.)"+ | otherwise = Outputable.empty++ mod_hidden pkg =+ text "it is a hidden module in the package" <+> quotes (ppr pkg)++ unusable (pkg, reason)+ = text "It is a member of the package"+ <+> quotes (ppr pkg)+ $$ pprReason (text "which is") reason++ pp_suggestions :: [ModuleSuggestion] -> SDoc+ pp_suggestions sugs+ | null sugs = Outputable.empty+ | otherwise = hang (text "Perhaps you meant")+ 2 (vcat (map pp_sugg sugs))++ -- NB: Prefer the *original* location, and then reexports, and then+ -- package flags when making suggestions. ToDo: if the original package+ -- also has a reexport, prefer that one+ pp_sugg (SuggestVisible m mod o) = ppr m <+> provenance o+ where provenance ModHidden = Outputable.empty+ provenance (ModUnusable _) = Outputable.empty+ provenance (ModOrigin{ fromOrigUnit = e,+ fromExposedReexport = res,+ fromPackageFlag = f })+ | Just True <- e+ = parens (text "from" <+> ppr (moduleUnit mod))+ | f && moduleName mod == m+ = parens (text "from" <+> ppr (moduleUnit mod))+ | (pkg:_) <- res+ = parens (text "from" <+> ppr (mkUnit pkg)+ <> comma <+> text "reexporting" <+> ppr mod)+ | f+ = parens (text "defined via package flags to be"+ <+> ppr mod)+ | otherwise = Outputable.empty+ pp_sugg (SuggestHidden m mod o) = ppr m <+> provenance o+ where provenance ModHidden = Outputable.empty+ provenance (ModUnusable _) = Outputable.empty+ provenance (ModOrigin{ fromOrigUnit = e,+ fromHiddenReexport = rhs })+ | Just False <- e+ = parens (text "needs flag -package-id"+ <+> ppr (moduleUnit mod))+ | (pkg:_) <- rhs+ = parens (text "needs flag -package-id"+ <+> ppr (mkUnit pkg))+ | otherwise = Outputable.empty+
compiler/GHC/Iface/Make.hs view
@@ -146,9 +146,9 @@ addFingerprints hsc_env partial_iface{ mi_decls = decls } -- Debug printing- let unit_state = unitState (hsc_dflags hsc_env)+ let unit_state = hsc_units hsc_env dumpIfSet_dyn (hsc_dflags hsc_env) Opt_D_dump_hi "FINAL INTERFACE" FormatText- (pprWithUnitState unit_state $ pprModIface full_iface)+ (pprModIface unit_state full_iface) return full_iface @@ -372,13 +372,11 @@ where sort_subs :: AvailInfo -> AvailInfo sort_subs (Avail n) = Avail n- sort_subs (AvailTC n [] fs) = AvailTC n [] (sort_flds fs)- sort_subs (AvailTC n (m:ms) fs)- | n==m = AvailTC n (m:sortBy stableNameCmp ms) (sort_flds fs)- | otherwise = AvailTC n (sortBy stableNameCmp (m:ms)) (sort_flds fs)+ sort_subs (AvailTC n []) = AvailTC n []+ sort_subs (AvailTC n (m:ms))+ | NormalGreName n==m = AvailTC n (m:sortBy stableGreNameCmp ms)+ | otherwise = AvailTC n (sortBy stableGreNameCmp (m:ms)) -- Maintain the AvailTC Invariant-- sort_flds = sortBy (stableNameCmp `on` flSelector) {- Note [Original module]
compiler/GHC/Iface/Recomp.hs view
@@ -377,7 +377,7 @@ checkFlagHash :: HscEnv -> ModIface -> IfG RecompileRequired checkFlagHash hsc_env iface = do let old_hash = mi_flag_hash (mi_final_exts iface)- new_hash <- liftIO $ fingerprintDynFlags (hsc_dflags hsc_env)+ new_hash <- liftIO $ fingerprintDynFlags hsc_env (mi_module iface) putNameLiterally case old_hash == new_hash of@@ -420,12 +420,12 @@ -- If the -unit-id flags change, this can change too. checkMergedSignatures :: ModSummary -> ModIface -> IfG RecompileRequired checkMergedSignatures mod_summary iface = do- dflags <- getDynFlags+ unit_state <- hsc_units <$> getTopEnv let old_merged = sort [ mod | UsageMergedRequirement{ usg_mod = mod } <- mi_usages iface ] new_merged = case Map.lookup (ms_mod_name mod_summary)- (requirementContext (unitState dflags)) of+ (requirementContext unit_state) of Nothing -> []- Just r -> sort $ map (instModuleToModule (unitState dflags)) r+ Just r -> sort $ map (instModuleToModule unit_state) r if old_merged == new_merged then up_to_date (text "signatures to merge in unchanged" $$ ppr new_merged) else return (RecompBecause "signatures to merge in changed")@@ -1061,7 +1061,7 @@ -- - (some of) dflags -- it returns two hashes, one that shouldn't change -- the abi hash and one that should- flag_hash <- fingerprintDynFlags dflags this_mod putNameLiterally+ flag_hash <- fingerprintDynFlags hsc_env this_mod putNameLiterally opt_hash <- fingerprintOptFlags dflags putNameLiterally
compiler/GHC/Iface/Recomp/Flags.hs view
@@ -10,8 +10,10 @@ import GHC.Prelude -import GHC.Utils.Binary import GHC.Driver.Session+import GHC.Driver.Env++import GHC.Utils.Binary import GHC.Unit.Module import GHC.Types.Name import GHC.Types.SafeHaskell@@ -29,12 +31,13 @@ -- NB: The 'Module' parameter is the 'Module' recorded by the -- *interface* file, not the actual 'Module' according to our -- 'DynFlags'.-fingerprintDynFlags :: DynFlags -> Module+fingerprintDynFlags :: HscEnv -> Module -> (BinHandle -> Name -> IO ()) -> IO Fingerprint -fingerprintDynFlags dflags@DynFlags{..} this_mod nameio =- let mainis = if mainModIs dflags == this_mod then Just mainFunIs else Nothing+fingerprintDynFlags hsc_env this_mod nameio =+ let dflags@DynFlags{..} = hsc_dflags hsc_env+ mainis = if mainModIs hsc_env == this_mod then Just mainFunIs else Nothing -- see #5878 -- pkgopts = (homeUnit home_unit, sort $ packageFlags dflags) safeHs = setSafeMode safeHaskell
compiler/GHC/Iface/Rename.hs view
@@ -145,7 +145,6 @@ -- because ModIface will never contain module reference for itself -- in these dependencies. fmap (nubSort . concat) . T.forM (sel deps) $ \mod -> do- dflags <- getDynFlags -- For holes, its necessary to "see through" the instantiation -- of the hole to get accurate family instance dependencies. -- For example, if B imports <A>, and <A> is instantiated with@@ -170,7 +169,7 @@ -- not to do it in this case either...) -- -- This mistake was bug #15594.- let mod' = renameHoleModule (unitState dflags) hmap mod+ let mod' = renameHoleModule (hsc_units hsc_env) hmap mod if isHoleModule mod then do iface <- liftIO . initIfaceCheck (text "rnDepModule") hsc_env $ loadSysInterface (text "rnDepModule") mod'@@ -190,9 +189,8 @@ -> ShIfM a -> IO (Either ErrorMessages a) initRnIface hsc_env iface insts nsubst do_this = do errs_var <- newIORef emptyBag- let dflags = hsc_dflags hsc_env- hsubst = listToUFM insts- rn_mod = renameHoleModule (unitState dflags) hsubst+ let hsubst = listToUFM insts+ rn_mod = renameHoleModule (hsc_units hsc_env) hsubst env = ShIfEnv { sh_if_module = rn_mod (mi_module iface), sh_if_semantic_module = rn_mod (mi_semantic_module iface),@@ -238,25 +236,30 @@ rnModule :: Rename Module rnModule mod = do hmap <- getHoleSubst- dflags <- getDynFlags- return (renameHoleModule (unitState dflags) hmap mod)+ unit_state <- hsc_units <$> getTopEnv+ return (renameHoleModule unit_state hmap mod) rnAvailInfo :: Rename AvailInfo-rnAvailInfo (Avail n) = Avail <$> rnIfaceGlobal n-rnAvailInfo (AvailTC n ns fs) = do+rnAvailInfo (Avail c) = Avail <$> rnGreName c+rnAvailInfo (AvailTC n ns) = do -- Why don't we rnIfaceGlobal the availName itself? It may not -- actually be exported by the module it putatively is from, in -- which case we won't be able to tell what the name actually -- is. But for the availNames they MUST be exported, so they -- will rename fine.- ns' <- mapM rnIfaceGlobal ns- fs' <- mapM rnFieldLabel fs- case ns' ++ map flSelector fs' of+ ns' <- mapM rnGreName ns+ case ns' of [] -> panic "rnAvailInfoEmpty AvailInfo"- (rep:rest) -> ASSERT2( all ((== nameModule rep) . nameModule) rest, ppr rep $$ hcat (map ppr rest) ) do- n' <- setNameModule (Just (nameModule rep)) n- return (AvailTC n' ns' fs')+ (rep:rest) -> ASSERT2( all ((== childModule rep) . childModule) rest, ppr rep $$ hcat (map ppr rest) ) do+ n' <- setNameModule (Just (childModule rep)) n+ return (AvailTC n' ns')+ where+ childModule = nameModule . greNameMangledName +rnGreName :: Rename GreName+rnGreName (NormalGreName n) = NormalGreName <$> rnIfaceGlobal n+rnGreName (FieldGreName fl) = FieldGreName <$> rnFieldLabel fl+ rnFieldLabel :: Rename FieldLabel rnFieldLabel (FieldLabel l b sel) = do sel' <- rnIfaceGlobal sel@@ -303,13 +306,13 @@ rnIfaceGlobal :: Name -> ShIfM Name rnIfaceGlobal n = do hsc_env <- getTopEnv- let dflags = hsc_dflags hsc_env- home_unit = hsc_home_unit hsc_env+ let unit_state = hsc_units hsc_env+ home_unit = hsc_home_unit hsc_env iface_semantic_mod <- fmap sh_if_semantic_module getGblEnv mb_nsubst <- fmap sh_if_shape getGblEnv hmap <- getHoleSubst let m = nameModule n- m' = renameHoleModule (unitState dflags) hmap m+ m' = renameHoleModule unit_state hmap m case () of -- Did we encounter {A.T} while renaming p[A=<B>]:A? If so, -- do NOT assume B.hi is available.@@ -368,9 +371,9 @@ rnIfaceNeverExported :: Name -> ShIfM Name rnIfaceNeverExported name = do hmap <- getHoleSubst- dflags <- getDynFlags+ unit_state <- hsc_units <$> getTopEnv iface_semantic_mod <- fmap sh_if_semantic_module getGblEnv- let m = renameHoleModule (unitState dflags) hmap $ nameModule name+ let m = renameHoleModule unit_state hmap $ nameModule name -- Doublecheck that this DFun/coercion axiom was, indeed, locally defined. MASSERT2( iface_semantic_mod == m, ppr iface_semantic_mod <+> ppr m ) setNameModule (Just m) name
compiler/GHC/Iface/Tidy.hs view
@@ -384,10 +384,7 @@ (const ()) $ do { let { omit_prags = gopt Opt_OmitInterfacePragmas dflags ; expose_all = gopt Opt_ExposeAllUnfoldings dflags- ; print_unqual = mkPrintUnqualified- (unitState dflags)- (hsc_home_unit hsc_env)- rdr_env+ ; print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) rdr_env ; implicit_binds = concatMap getImplicitBinds tcs }
compiler/GHC/Linker/Dynamic.hs view
@@ -16,9 +16,9 @@ import GHC.Driver.Session +import GHC.Unit.Env import GHC.Unit.Types import GHC.Unit.State-import GHC.Utils.Outputable import GHC.Linker.MacOS import GHC.Linker.Unit import GHC.SysTools.Tasks@@ -26,11 +26,11 @@ import qualified Data.Set as Set import System.FilePath -linkDynLib :: DynFlags -> [String] -> [UnitId] -> IO ()-linkDynLib dflags0 o_files dep_packages+linkDynLib :: DynFlags -> UnitEnv -> [String] -> [UnitId] -> IO ()+linkDynLib dflags0 unit_env o_files dep_packages = do- let platform = targetPlatform dflags0- os = platformOS platform+ let platform = ue_platform unit_env+ os = platformOS platform -- This is a rather ugly hack to fix dynamically linked -- GHC on Windows. If GHC is linked with -threaded, then@@ -47,22 +47,17 @@ verbFlags = getVerbFlags dflags o_file = outputFile dflags - pkgs_with_rts <- getPreloadUnitsAnd- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- (mkHomeUnitFromFlags dflags)- dep_packages+ pkgs_with_rts <- mayThrowUnitErr (preloadUnitsInfo' unit_env dep_packages) - let pkg_lib_paths = collectLibraryPaths (ways dflags) pkgs_with_rts+ let pkg_lib_paths = collectLibraryDirs (ways dflags) pkgs_with_rts let pkg_lib_path_opts = concatMap get_pkg_lib_path_opts pkg_lib_paths get_pkg_lib_path_opts l- | ( osElfTarget (platformOS (targetPlatform dflags)) ||- osMachOTarget (platformOS (targetPlatform dflags)) ) &&- dynLibLoader dflags == SystemDependent &&- -- Only if we want dynamic libraries- WayDyn `Set.member` ways dflags &&+ | osElfTarget os || osMachOTarget os+ , dynLibLoader dflags == SystemDependent+ , -- Only if we want dynamic libraries+ WayDyn `Set.member` ways dflags -- Only use RPath if we explicitly asked for it- gopt Opt_RPath dflags+ , gopt Opt_RPath dflags = ["-L" ++ l, "-Xlinker", "-rpath", "-Xlinker", l] -- See Note [-Xlinker -rpath vs -Wl,-rpath] | otherwise = ["-L" ++ l]@@ -96,8 +91,7 @@ let extra_ld_inputs = ldInputs dflags -- frameworks- pkg_framework_opts <- getUnitFrameworkOpts dflags platform- (map unitId pkgs)+ pkg_framework_opts <- getUnitFrameworkOpts unit_env (map unitId pkgs) let framework_opts = getFrameworkOpts dflags platform case os of
compiler/GHC/Linker/ExtraObj.hs view
@@ -20,33 +20,36 @@ ) where +import GHC.Prelude+import GHC.Platform++import GHC.Unit+import GHC.Unit.Env+import GHC.Unit.State+ import GHC.Utils.Asm import GHC.Utils.Error+import GHC.Utils.Misc+import GHC.Utils.Outputable as Outputable+ import GHC.Driver.Session import GHC.Driver.Ppr-import GHC.Unit.State-import GHC.Platform-import GHC.Utils.Outputable as Outputable+ import GHC.Types.SrcLoc ( noSrcSpan )-import GHC.Unit-import GHC.SysTools.Elf-import GHC.Utils.Misc-import GHC.Prelude import qualified GHC.Data.ShortText as ST -import Control.Monad-import Data.Maybe--import Control.Monad.IO.Class-+import GHC.SysTools.Elf import GHC.SysTools.FileCleanup import GHC.SysTools.Tasks import GHC.SysTools.Info import GHC.Linker.Unit-import GHC.Linker.MacOS -mkExtraObj :: DynFlags -> Suffix -> String -> IO FilePath-mkExtraObj dflags extn xs+import Control.Monad.IO.Class+import Control.Monad+import Data.Maybe++mkExtraObj :: DynFlags -> UnitState -> Suffix -> String -> IO FilePath+mkExtraObj dflags unit_state extn xs = do cFile <- newTempName dflags TFL_CurrentModule extn oFile <- newTempName dflags TFL_GhcSession "o" writeFile cFile xs@@ -61,14 +64,12 @@ else asmOpts ccInfo) return oFile where- pkgs = unitState dflags- -- Pass a different set of options to the C compiler depending one whether -- we're compiling C or assembler. When compiling C, we pass the usual -- set of include directories and PIC flags. cOpts = map Option (picCCOpts dflags) ++ map (FileOption "-I" . ST.unpack)- (unitIncludeDirs $ unsafeLookupUnit pkgs rtsUnit)+ (unitIncludeDirs $ unsafeLookupUnit unit_state rtsUnit) -- When compiling assembler code, we drop the usual C options, and if the -- compiler is Clang, we add an extra argument to tell Clang to ignore@@ -86,15 +87,15 @@ -- -- On Windows, when making a shared library we also may need a DllMain. ---mkExtraObjToLinkIntoBinary :: DynFlags -> IO FilePath-mkExtraObjToLinkIntoBinary dflags = do+mkExtraObjToLinkIntoBinary :: DynFlags -> UnitState -> IO FilePath+mkExtraObjToLinkIntoBinary dflags unit_state = do when (gopt Opt_NoHsMain dflags && haveRtsOptsFlags dflags) $ putLogMsg dflags NoReason SevInfo noSrcSpan $ withPprStyle defaultUserStyle (text "Warning: -rtsopts and -with-rtsopts have no effect with -no-hs-main." $$ text " Call hs_init_ghc() from your main() function to set these options.") - mkExtraObj dflags "c" (showSDoc dflags main)+ mkExtraObj dflags unit_state "c" (showSDoc dflags main) where main | gopt Opt_NoHsMain dflags = Outputable.empty@@ -152,53 +153,52 @@ -- this was included as inline assembly in the main.c file but this -- is pretty fragile. gas gets upset trying to calculate relative offsets -- that span the .note section (notably .text) when debug info is present-mkNoteObjsToLinkIntoBinary :: DynFlags -> [UnitId] -> IO [FilePath]-mkNoteObjsToLinkIntoBinary dflags dep_packages = do- link_info <- getLinkInfo dflags dep_packages+mkNoteObjsToLinkIntoBinary :: DynFlags -> UnitEnv -> [UnitId] -> IO [FilePath]+mkNoteObjsToLinkIntoBinary dflags unit_env dep_packages = do+ link_info <- getLinkInfo dflags unit_env dep_packages if (platformSupportsSavingLinkOpts (platformOS platform ))- then fmap (:[]) $ mkExtraObj dflags "s" (showSDoc dflags (link_opts link_info))+ then fmap (:[]) $ mkExtraObj dflags unit_state "s" (showSDoc dflags (link_opts link_info)) else return [] where- platform = targetPlatform dflags- link_opts info = hcat [- -- "link info" section (see Note [LinkInfo section])- makeElfNote platform ghcLinkInfoSectionName ghcLinkInfoNoteName 0 info,+ unit_state = ue_units unit_env+ platform = ue_platform unit_env+ link_opts info = hcat+ [ -- "link info" section (see Note [LinkInfo section])+ makeElfNote platform ghcLinkInfoSectionName ghcLinkInfoNoteName 0 info - -- ALL generated assembly must have this section to disable- -- executable stacks. See also- -- "GHC.CmmToAsm" for another instance- -- where we need to do this.- if platformHasGnuNonexecStack platform- then text ".section .note.GNU-stack,\"\","- <> sectionType platform "progbits" <> char '\n'- else Outputable.empty- ]+ -- ALL generated assembly must have this section to disable+ -- executable stacks. See also+ -- "GHC.CmmToAsm" for another instance+ -- where we need to do this.+ , if platformHasGnuNonexecStack platform+ then text ".section .note.GNU-stack,\"\","+ <> sectionType platform "progbits" <> char '\n'+ else Outputable.empty+ ] -- | Return the "link info" string -- -- See Note [LinkInfo section]-getLinkInfo :: DynFlags -> [UnitId] -> IO String-getLinkInfo dflags dep_packages = do- package_link_opts <- getUnitLinkOpts dflags dep_packages- let unit_state = unitState dflags- home_unit = mkHomeUnitFromFlags dflags- ctx = initSDocContext dflags defaultUserStyle- pkg_frameworks <- if platformUsesFrameworks (targetPlatform dflags)- then getUnitFrameworks ctx unit_state home_unit dep_packages- else return []- let extra_ld_inputs = ldInputs dflags- let- link_info = (package_link_opts,- pkg_frameworks,- rtsOpts dflags,- rtsOptsEnabled dflags,- gopt Opt_NoHsMain dflags,- map showOpt extra_ld_inputs,- getOpts dflags opt_l)- --- return (show link_info)+getLinkInfo :: DynFlags -> UnitEnv -> [UnitId] -> IO String+getLinkInfo dflags unit_env dep_packages = do+ package_link_opts <- getUnitLinkOpts dflags unit_env dep_packages+ pkg_frameworks <- if not (platformUsesFrameworks (ue_platform unit_env))+ then return []+ else do+ ps <- mayThrowUnitErr (preloadUnitsInfo' unit_env dep_packages)+ return (collectFrameworks ps)+ let link_info =+ ( package_link_opts+ , pkg_frameworks+ , rtsOpts dflags+ , rtsOptsEnabled dflags+ , gopt Opt_NoHsMain dflags+ , map showOpt (ldInputs dflags)+ , getOpts dflags opt_l+ )+ return (show link_info) platformSupportsSavingLinkOpts :: OS -> Bool platformSupportsSavingLinkOpts os@@ -216,9 +216,9 @@ -- Returns 'False' if it was, and we can avoid linking, because the -- previous binary was linked with "the same options".-checkLinkInfo :: DynFlags -> [UnitId] -> FilePath -> IO Bool-checkLinkInfo dflags pkg_deps exe_file- | not (platformSupportsSavingLinkOpts (platformOS (targetPlatform dflags)))+checkLinkInfo :: DynFlags -> UnitEnv -> [UnitId] -> FilePath -> IO Bool+checkLinkInfo dflags unit_env pkg_deps exe_file+ | not (platformSupportsSavingLinkOpts (platformOS (ue_platform unit_env))) -- ToDo: Windows and OS X do not use the ELF binary format, so -- readelf does not work there. We need to find another way to do -- this.@@ -227,7 +227,7 @@ -- time so we leave it as-is. | otherwise = do- link_info <- getLinkInfo dflags pkg_deps+ link_info <- getLinkInfo dflags unit_env pkg_deps debugTraceMsg dflags 3 $ text ("Link info: " ++ link_info) m_exe_link_info <- readElfNoteAsString dflags exe_file ghcLinkInfoSectionName ghcLinkInfoNoteName
compiler/GHC/Linker/Loader.hs view
@@ -35,6 +35,8 @@ import GHC.Prelude +import GHC.Settings+ import GHC.Platform import GHC.Platform.Ways @@ -69,6 +71,7 @@ import GHC.Utils.Misc import GHC.Utils.Error +import GHC.Unit.Env import GHC.Unit.Finder import GHC.Unit.Module import GHC.Unit.Module.ModIface@@ -280,14 +283,13 @@ reallyInitLoaderState :: HscEnv -> IO LoaderState reallyInitLoaderState hsc_env = do -- Initialise the linker state- let dflags = hsc_dflags hsc_env- pls0 = emptyLS+ let pls0 = emptyLS -- (a) initialise the C dynamic linker initObjLinker hsc_env -- (b) Load packages from the command-line (Note [preload packages])- pls <- loadPackages' hsc_env (preloadUnits (unitState dflags)) pls0+ pls <- loadPackages' hsc_env (preloadUnits (hsc_units hsc_env)) pls0 -- steps (c), (d) and (e) loadCmdLineLibs' hsc_env pls@@ -911,8 +913,9 @@ dynLoadObjs :: HscEnv -> LoaderState -> [FilePath] -> IO LoaderState dynLoadObjs _ pls [] = return pls dynLoadObjs hsc_env pls@LoaderState{..} objs = do+ let unit_env = hsc_unit_env hsc_env let dflags = hsc_dflags hsc_env- let platform = targetPlatform dflags+ let platform = ue_platform unit_env let minus_ls = [ lib | Option ('-':'l':lib) <- ldInputs dflags ] let minus_big_ls = [ lib | Option ('-':'L':lib) <- ldInputs dflags ] (soFile, libPath , libName) <-@@ -962,7 +965,7 @@ -- link all "loaded packages" so symbols in those can be resolved -- Note: We are loading packages with local scope, so to see the -- symbols in this link we must link all loaded packages again.- linkDynLib dflags2 objs pkgs_loaded+ linkDynLib dflags2 unit_env objs pkgs_loaded -- if we got this far, extend the lifetime of the library file changeTempFilesLifetime dflags TFL_GhcSession [soFile]@@ -1250,9 +1253,6 @@ pkgs' <- link (pkgs_loaded pls) new_pks return $! pls { pkgs_loaded = pkgs' } where- dflags = hsc_dflags hsc_env- pkgstate = unitState dflags- link :: [UnitId] -> [UnitId] -> IO [UnitId] link pkgs new_pkgs = foldM link_one pkgs new_pkgs@@ -1261,7 +1261,7 @@ | new_pkg `elem` pkgs -- Already linked = return pkgs - | Just pkg_cfg <- lookupUnitId pkgstate new_pkg+ | Just pkg_cfg <- lookupUnitId (hsc_units hsc_env) new_pkg = do { -- Link dependents first pkgs' <- link pkgs (unitDepends pkg_cfg) -- Now link the package itself@@ -1522,7 +1522,7 @@ , "lib" ++ lib <.> "dll.a", lib <.> "dll.a" ] - hs_dyn_lib_name = lib ++ '-':programName dflags ++ projectVersion dflags+ hs_dyn_lib_name = lib ++ dynLibSuffix (ghcNameVersion dflags) hs_dyn_lib_file = platformHsSOName platform hs_dyn_lib_name so_name = platformSOName platform lib
compiler/GHC/Linker/MacOS.hs view
@@ -1,8 +1,6 @@ module GHC.Linker.MacOS ( runInjectRPaths- , getUnitFrameworks , getUnitFrameworkOpts- , getUnitFrameworkPath , getFrameworkOpts , loadFramework )@@ -16,18 +14,14 @@ import GHC.Unit.Types import GHC.Unit.State-import GHC.Unit.Home+import GHC.Unit.Env import GHC.SysTools.Tasks import GHC.Runtime.Interpreter (loadDLL) -import GHC.Utils.Outputable import GHC.Utils.Exception-import GHC.Utils.Misc (ordNub ) -import qualified GHC.Data.ShortText as ST- import Data.List import Control.Monad (join, forM, filterM) import System.Directory (doesFileExist, getHomeDirectory)@@ -67,26 +61,15 @@ [] -> return () _ -> runInstallNameTool dflags $ map Option $ "-add_rpath":(intersperse "-add_rpath" rpaths) ++ [dylib] -getUnitFrameworkOpts :: DynFlags -> Platform -> [UnitId] -> IO [String]-getUnitFrameworkOpts dflags platform dep_packages- | platformUsesFrameworks platform = do- pkg_framework_path_opts <- do- pkg_framework_paths <- getUnitFrameworkPath- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- (mkHomeUnitFromFlags dflags)- dep_packages- return $ map ("-F" ++) pkg_framework_paths-- pkg_framework_opts <- do- pkg_frameworks <- getUnitFrameworks- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- (mkHomeUnitFromFlags dflags)- dep_packages- return $ concat [ ["-framework", fw] | fw <- pkg_frameworks ]-- return (pkg_framework_path_opts ++ pkg_framework_opts)+getUnitFrameworkOpts :: UnitEnv -> [UnitId] -> IO [String]+getUnitFrameworkOpts unit_env dep_packages+ | platformUsesFrameworks (ue_platform unit_env) = do+ ps <- mayThrowUnitErr (preloadUnitsInfo' unit_env dep_packages)+ let pkg_framework_path_opts = map ("-F" ++) (collectFrameworksDirs ps)+ pkg_framework_opts = concat [ ["-framework", fw]+ | fw <- collectFrameworks ps+ ]+ return (pkg_framework_path_opts ++ pkg_framework_opts) | otherwise = return [] @@ -102,19 +85,6 @@ -- reverse because they're added in reverse order from the cmd line: framework_opts = concat [ ["-framework", fw] | fw <- reverse frameworks ]----- | Find all the package framework paths in these and the preload packages-getUnitFrameworkPath :: SDocContext -> UnitState -> HomeUnit -> [UnitId] -> IO [String]-getUnitFrameworkPath ctx unit_state home_unit pkgs = do- ps <- getPreloadUnitsAnd ctx unit_state home_unit pkgs- return $ map ST.unpack (ordNub (filter (not . ST.null) (concatMap unitExtDepFrameworkDirs ps)))---- | Find all the package frameworks in these and the preload packages-getUnitFrameworks :: SDocContext -> UnitState -> HomeUnit -> [UnitId] -> IO [String]-getUnitFrameworks ctx unit_state home_unit pkgs = do- ps <- getPreloadUnitsAnd ctx unit_state home_unit pkgs- return $ map ST.unpack (concatMap unitExtDepFrameworks ps) {-
compiler/GHC/Linker/Static.hs view
@@ -15,13 +15,13 @@ import GHC.SysTools.Ar import GHC.SysTools.FileCleanup +import GHC.Unit.Env import GHC.Unit.Types import GHC.Unit.Info import GHC.Unit.State import GHC.Utils.Monad import GHC.Utils.Misc-import GHC.Utils.Outputable import GHC.Linker.MacOS import GHC.Linker.Unit@@ -62,16 +62,16 @@ -Xlinker, but not -Wl. -} -linkBinary :: DynFlags -> [FilePath] -> [UnitId] -> IO ()+linkBinary :: DynFlags -> UnitEnv -> [FilePath] -> [UnitId] -> IO () linkBinary = linkBinary' False -linkBinary' :: Bool -> DynFlags -> [FilePath] -> [UnitId] -> IO ()-linkBinary' staticLink dflags o_files dep_units = do- let platform = targetPlatform dflags+linkBinary' :: Bool -> DynFlags -> UnitEnv -> [FilePath] -> [UnitId] -> IO ()+linkBinary' staticLink dflags unit_env o_files dep_units = do+ let platform = ue_platform unit_env+ unit_state = ue_units unit_env toolSettings' = toolSettings dflags verbFlags = getVerbFlags dflags output_fn = exeFileName platform staticLink (outputFile dflags)- home_unit = mkHomeUnitFromFlags dflags -- get the full list of packages to link with, by combining the -- explicit packages with the auto packages and all of their@@ -81,12 +81,8 @@ then return output_fn else do d <- getCurrentDirectory return $ normalise (d </> output_fn)- pkg_lib_paths <- getUnitLibraryPath- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- home_unit- (ways dflags)- dep_units+ pkgs <- mayThrowUnitErr (preloadUnitsInfo' unit_env dep_units)+ let pkg_lib_paths = collectLibraryDirs (ways dflags) pkgs let pkg_lib_path_opts = concatMap get_pkg_lib_path_opts pkg_lib_paths get_pkg_lib_path_opts l | osElfTarget (platformOS platform) &&@@ -124,7 +120,7 @@ pkg_lib_path_opts <- if gopt Opt_SingleLibFolder dflags then do- libs <- getLibs dflags dep_units+ libs <- getLibs dflags unit_env dep_units tmpDir <- newTempDir dflags sequence_ [ copyFile lib (tmpDir </> basename) | (lib, basename) <- libs]@@ -140,8 +136,8 @@ let lib_paths = libraryPaths dflags let lib_path_opts = map ("-L"++) lib_paths - extraLinkObj <- mkExtraObjToLinkIntoBinary dflags- noteLinkObjs <- mkNoteObjsToLinkIntoBinary dflags dep_units+ extraLinkObj <- mkExtraObjToLinkIntoBinary dflags unit_state+ noteLinkObjs <- mkNoteObjsToLinkIntoBinary dflags unit_env dep_units let (pre_hs_libs, post_hs_libs)@@ -154,7 +150,7 @@ = ([],[]) pkg_link_opts <- do- (package_hs_libs, extra_libs, other_flags) <- getUnitLinkOpts dflags dep_units+ (package_hs_libs, extra_libs, other_flags) <- getUnitLinkOpts dflags unit_env dep_units return $ if staticLink then package_hs_libs -- If building an executable really means making a static -- library (e.g. iOS), then we only keep the -l options for@@ -176,7 +172,7 @@ -- that defines the symbol." -- frameworks- pkg_framework_opts <- getUnitFrameworkOpts dflags platform dep_units+ pkg_framework_opts <- getUnitFrameworkOpts unit_env dep_units let framework_opts = getFrameworkOpts dflags platform -- probably _stub.o files@@ -273,13 +269,12 @@ -- | Linking a static lib will not really link anything. It will merely produce -- a static archive of all dependent static libraries. The resulting library -- will still need to be linked with any remaining link flags.-linkStaticLib :: DynFlags -> [String] -> [UnitId] -> IO ()-linkStaticLib dflags o_files dep_units = do- let platform = targetPlatform dflags+linkStaticLib :: DynFlags -> UnitEnv -> [String] -> [UnitId] -> IO ()+linkStaticLib dflags unit_env o_files dep_units = do+ let platform = ue_platform unit_env extra_ld_inputs = [ f | FileOption _ f <- ldInputs dflags ] modules = o_files ++ extra_ld_inputs output_fn = exeFileName platform True (outputFile dflags)- home_unit = mkHomeUnitFromFlags dflags full_output_fn <- if isAbsolute output_fn then return output_fn@@ -288,11 +283,7 @@ output_exists <- doesFileExist full_output_fn (when output_exists) $ removeFile full_output_fn - pkg_cfgs_init <- getPreloadUnitsAnd- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- home_unit- dep_units+ pkg_cfgs_init <- mayThrowUnitErr (preloadUnitsInfo' unit_env dep_units) let pkg_cfgs | gopt Opt_LinkRts dflags
compiler/GHC/Linker/Unit.hs view
@@ -3,11 +3,8 @@ module GHC.Linker.Unit ( collectLinkOpts , collectArchives- , collectLibraryPaths , getUnitLinkOpts- , getUnitLibraryPath , getLibs- , packageHsLibs ) where @@ -16,35 +13,28 @@ import GHC.Unit.Types import GHC.Unit.Info import GHC.Unit.State-import GHC.Unit.Home-import GHC.Utils.Outputable-import GHC.Utils.Panic+import GHC.Unit.Env import GHC.Utils.Misc import qualified GHC.Data.ShortText as ST import GHC.Driver.Session -import qualified Data.Set as Set-import Data.List (isPrefixOf, stripPrefix) import Control.Monad import System.Directory import System.FilePath -- | Find all the link options in these and the preload packages, -- returning (package hs lib options, extra library options, other flags)-getUnitLinkOpts :: DynFlags -> [UnitId] -> IO ([String], [String], [String])-getUnitLinkOpts dflags pkgs =- collectLinkOpts dflags `fmap` getPreloadUnitsAnd- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- (mkHomeUnitFromFlags dflags)- pkgs+getUnitLinkOpts :: DynFlags -> UnitEnv -> [UnitId] -> IO ([String], [String], [String])+getUnitLinkOpts dflags unit_env pkgs = do+ ps <- mayThrowUnitErr $ preloadUnitsInfo' unit_env pkgs+ return (collectLinkOpts dflags ps) collectLinkOpts :: DynFlags -> [UnitInfo] -> ([String], [String], [String]) collectLinkOpts dflags ps = (- concatMap (map ("-l" ++) . packageHsLibs dflags) ps,+ concatMap (map ("-l" ++) . unitHsLibs (ghcNameVersion dflags) (ways dflags)) ps, concatMap (map ("-l" ++) . map ST.unpack . unitExtDepLibsSys) ps, concatMap (map ST.unpack . unitLinkerOptions) ps )@@ -55,11 +45,7 @@ | searchPath <- searchPaths , lib <- libs ] where searchPaths = ordNub . filter notNull . libraryDirsForWay (ways dflags) $ pc- libs = packageHsLibs dflags pc ++ map ST.unpack (unitExtDepLibsSys pc)--collectLibraryPaths :: Ways -> [UnitInfo] -> [FilePath]-collectLibraryPaths ws = ordNub . filter notNull- . concatMap (libraryDirsForWay ws)+ libs = unitHsLibs (ghcNameVersion dflags) (ways dflags) pc ++ map ST.unpack (unitExtDepLibsSys pc) -- | Either the 'unitLibraryDirs' or 'unitLibraryDynDirs' as appropriate for the way. libraryDirsForWay :: Ways -> UnitInfo -> [String]@@ -67,68 +53,11 @@ | WayDyn `elem` ws = map ST.unpack . unitLibraryDynDirs | otherwise = map ST.unpack . unitLibraryDirs -getLibs :: DynFlags -> [UnitId] -> IO [(String,String)]-getLibs dflags pkgs = do- ps <- getPreloadUnitsAnd- (initSDocContext dflags defaultUserStyle)- (unitState dflags)- (mkHomeUnitFromFlags dflags)- pkgs+getLibs :: DynFlags -> UnitEnv -> [UnitId] -> IO [(String,String)]+getLibs dflags unit_env pkgs = do+ ps <- mayThrowUnitErr $ preloadUnitsInfo' unit_env pkgs fmap concat . forM ps $ \p -> do- let candidates = [ (l </> f, f) | l <- collectLibraryPaths (ways dflags) [p]- , f <- (\n -> "lib" ++ n ++ ".a") <$> packageHsLibs dflags p ]+ let candidates = [ (l </> f, f) | l <- collectLibraryDirs (ways dflags) [p]+ , f <- (\n -> "lib" ++ n ++ ".a") <$> unitHsLibs (ghcNameVersion dflags) (ways dflags) p ] filterM (doesFileExist . fst) candidates---- | Find all the library paths in these and the preload packages-getUnitLibraryPath :: SDocContext -> UnitState -> HomeUnit -> Ways -> [UnitId] -> IO [String]-getUnitLibraryPath ctx unit_state home_unit ws pkgs =- collectLibraryPaths ws `fmap` getPreloadUnitsAnd ctx unit_state home_unit pkgs--packageHsLibs :: DynFlags -> UnitInfo -> [String]-packageHsLibs dflags p = map (mkDynName . addSuffix . ST.unpack) (unitLibraries p)- where- ways0 = ways dflags-- ways1 = Set.filter (/= WayDyn) ways0- -- the name of a shared library is libHSfoo-ghc<version>.so- -- we leave out the _dyn, because it is superfluous-- -- debug and profiled RTSs include support for -eventlog- ways2 | WayDebug `Set.member` ways1 || WayProf `Set.member` ways1- = Set.filter (/= WayTracing) ways1- | otherwise- = ways1-- tag = waysTag (fullWays ways2)- rts_tag = waysTag ways2-- mkDynName x- | not (ways dflags `hasWay` WayDyn) = x- | "HS" `isPrefixOf` x =- x ++ '-':programName dflags ++ projectVersion dflags- -- For non-Haskell libraries, we use the name "Cfoo". The .a- -- file is libCfoo.a, and the .so is libfoo.so. That way the- -- linker knows what we mean for the vanilla (-lCfoo) and dyn- -- (-lfoo) ways. We therefore need to strip the 'C' off here.- | Just x' <- stripPrefix "C" x = x'- | otherwise- = panic ("Don't understand library name " ++ x)-- -- Add _thr and other rts suffixes to packages named- -- `rts` or `rts-1.0`. Why both? Traditionally the rts- -- package is called `rts` only. However the tooling- -- usually expects a package name to have a version.- -- As such we will gradually move towards the `rts-1.0`- -- package name, at which point the `rts` package name- -- will eventually be unused.- --- -- This change elevates the need to add custom hooks- -- and handling specifically for the `rts` package for- -- example in ghc-cabal.- addSuffix rts@"HSrts" = rts ++ (expandTag rts_tag)- addSuffix rts@"HSrts-1.0"= rts ++ (expandTag rts_tag)- addSuffix other_lib = other_lib ++ (expandTag tag)-- expandTag t | null t = ""- | otherwise = '_':t
+ compiler/GHC/Parser/Utils.hs view
@@ -0,0 +1,58 @@+module GHC.Parser.Utils+ ( isStmt+ , hasImport+ , isImport+ , isDecl+ )+where++import GHC.Prelude+import GHC.Hs+import GHC.Data.StringBuffer+import GHC.Data.FastString+import GHC.Types.SrcLoc++import qualified GHC.Parser.Lexer as Lexer (P (..), ParseResult(..), unP, initParserState)+import GHC.Parser.Lexer (ParserOpts)+import qualified GHC.Parser as Parser (parseStmt, parseModule, parseDeclaration, parseImport)+++-- | Returns @True@ if passed string is a statement.+isStmt :: ParserOpts -> String -> Bool+isStmt pflags stmt =+ case parseThing Parser.parseStmt pflags stmt of+ Lexer.POk _ _ -> True+ Lexer.PFailed _ -> False++-- | Returns @True@ if passed string has an import declaration.+hasImport :: ParserOpts -> String -> Bool+hasImport pflags stmt =+ case parseThing Parser.parseModule pflags stmt of+ Lexer.POk _ thing -> hasImports thing+ Lexer.PFailed _ -> False+ where+ hasImports = not . null . hsmodImports . unLoc++-- | Returns @True@ if passed string is an import declaration.+isImport :: ParserOpts -> String -> Bool+isImport pflags stmt =+ case parseThing Parser.parseImport pflags stmt of+ Lexer.POk _ _ -> True+ Lexer.PFailed _ -> False++-- | Returns @True@ if passed string is a declaration but __/not a splice/__.+isDecl :: ParserOpts -> String -> Bool+isDecl pflags stmt =+ case parseThing Parser.parseDeclaration pflags stmt of+ Lexer.POk _ thing ->+ case unLoc thing of+ SpliceD _ _ -> False+ _ -> True+ Lexer.PFailed _ -> False++parseThing :: Lexer.P thing -> ParserOpts -> String -> Lexer.ParseResult thing+parseThing parser opts stmt = do+ let buf = stringToStringBuffer stmt+ loc = mkRealSrcLoc (fsLit "<interactive>") 1 1++ Lexer.unP parser (Lexer.initParserState opts buf loc)
compiler/GHC/Rename/Bind.hs view
@@ -47,6 +47,7 @@ , addNoNestedForallsContextsErr, checkInferredVars ) import GHC.Driver.Session import GHC.Unit.Module+import GHC.Types.FieldLabel import GHC.Types.Name import GHC.Types.Name.Env import GHC.Types.Name.Set@@ -679,10 +680,10 @@ -- so that the binding locations are reported -- from the left-hand side case details of- PrefixCon vars ->+ PrefixCon _ vars -> do { checkDupRdrNames vars ; names <- mapM lookupPatSynBndr vars- ; return ( (pat', PrefixCon names)+ ; return ( (pat', PrefixCon noTypeArgs names) , mkFVs (map unLoc names)) } InfixCon var1 var2 -> do { checkDupRdrNames [var1, var2]@@ -692,13 +693,15 @@ ; return ( (pat', InfixCon name1 name2) , mkFVs (map unLoc [name1, name2])) } RecCon vars ->- do { checkDupRdrNames (map recordPatSynSelectorId vars)+ do { checkDupRdrNames (map (rdrNameFieldOcc . recordPatSynField) vars)+ ; fls <- lookupConstructorFields name+ ; let fld_env = mkFsEnv [ (flLabel fl, fl) | fl <- fls ] ; let rnRecordPatSynField- (RecordPatSynField { recordPatSynSelectorId = visible+ (RecordPatSynField { recordPatSynField = visible , recordPatSynPatVar = hidden })- = do { visible' <- lookupLocatedTopBndrRn visible+ = do { let visible' = lookupField fld_env visible ; hidden' <- lookupPatSynBndr hidden- ; return $ RecordPatSynField { recordPatSynSelectorId = visible'+ ; return $ RecordPatSynField { recordPatSynField = visible' , recordPatSynPatVar = hidden' } } ; names <- mapM rnRecordPatSynField vars ; return ( (pat', RecCon names)@@ -726,7 +729,7 @@ , psb_ext = fvs' } selector_names = case details' of RecCon names ->- map (unLoc . recordPatSynSelectorId) names+ map (extFieldOcc . recordPatSynField) names _ -> [] ; fvs' `seq` -- See Note [Free-variable space leak]
compiler/GHC/Rename/Env.hs view
@@ -267,7 +267,7 @@ ; env <- getGlobalRdrEnv ; case filter isLocalGRE (lookupGRE_RdrName rdr_name env) of- [gre] -> return (gre_name gre)+ [gre] -> return (greMangledName gre) _ -> do -- Ambiguous (can't happen) or unbound traceRn "lookupTopBndrRN fail" (ppr rdr_name) unboundName WL_LocalTop rdr_name@@ -307,9 +307,9 @@ Nothing -> [] gres = [ gre | occ <- main_occ : demoted_occs , gre <- lookupGlobalRdrEnv env occ- , gre_name gre == name ]+ , greMangledName gre == name ] ; case gres of- [gre] -> return (Right (gre_name gre))+ [gre] -> return (Right (greMangledName gre)) [] -> -- See Note [Splicing Exact names] do { lcl_env <- getLocalRdrEnv@@ -332,7 +332,7 @@ = hang (text "Same exact name in multiple name-spaces:") 2 (vcat (map pp_one sorted_names) $$ th_hint) where- sorted_names = sortBy (SrcLoc.leftmost_smallest `on` nameSrcSpan) (map gre_name gres)+ sorted_names = sortBy (SrcLoc.leftmost_smallest `on` nameSrcSpan) (map greMangledName gres) pp_one name = hang (pprNameSpace (occNameSpace (getOccName name)) <+> quotes (ppr name) <> comma)@@ -598,7 +598,7 @@ lookupSubBndrOcc_helper must_have_parent warn_if_deprec parent rdr_name | isUnboundName parent -- Avoid an error cascade- = return (FoundName NoParent (mkUnboundNameRdr rdr_name))+ = return (FoundChild NoParent (NormalGreName (mkUnboundNameRdr rdr_name))) | otherwise = do gre_env <- getGlobalRdrEnv@@ -624,20 +624,9 @@ where -- Convert into FieldLabel if necessary checkFld :: GlobalRdrElt -> RnM ChildLookupResult- checkFld g@GRE{gre_name, gre_par} = do+ checkFld g@GRE{gre_name,gre_par} = do addUsedGRE warn_if_deprec g- return $ case gre_par of- FldParent _ mfs ->- FoundFL (fldParentToFieldLabel gre_name mfs)- _ -> FoundName gre_par gre_name-- fldParentToFieldLabel :: Name -> Maybe FastString -> FieldLabel- fldParentToFieldLabel name mfs =- case mfs of- Nothing ->- let fs = occNameFS (nameOccName name)- in FieldLabel fs False name- Just fs -> FieldLabel fs True name+ return $ FoundChild gre_par gre_name -- Called when we find no matching GREs after disambiguation but -- there are three situations where this happens.@@ -655,27 +644,25 @@ case original_gres of [] -> return NameNotFound [g] -> return $ IncorrectParent parent- (gre_name g) (ppr $ gre_name g)+ (gre_name g) [p | Just p <- [getParent g]] gss@(g:_:_) -> if all isRecFldGRE gss && overload_ok then return $ IncorrectParent parent (gre_name g)- (ppr $ expectJust "noMatchingParentErr" (greLabel g)) [p | x <- gss, Just p <- [getParent x]] else mkNameClashErr gss mkNameClashErr :: [GlobalRdrElt] -> RnM ChildLookupResult mkNameClashErr gres = do addNameClashErrRn rdr_name gres- return (FoundName (gre_par (head gres)) (gre_name (head gres)))+ return (FoundChild (gre_par (head gres)) (gre_name (head gres))) getParent :: GlobalRdrElt -> Maybe Name getParent (GRE { gre_par = p } ) = case p of ParentIs cur_parent -> Just cur_parent- FldParent { par_is = cur_parent } -> Just cur_parent NoParent -> Nothing picked_gres :: [GlobalRdrElt] -> DisambigInfo@@ -743,11 +730,9 @@ data ChildLookupResult = NameNotFound -- We couldn't find a suitable name | IncorrectParent Name -- Parent- Name -- Name of thing we were looking for- SDoc -- How to print the name+ GreName -- Child we were looking for [Name] -- List of possible parents- | FoundName Parent Name -- We resolved to a normal name- | FoundFL FieldLabel -- We resolved to a FL+ | FoundChild Parent GreName -- We resolved to a child -- | Specialised version of msum for RnM ChildLookupResult combineChildLookupResult :: [RnM ChildLookupResult] -> RnM ChildLookupResult@@ -760,10 +745,9 @@ instance Outputable ChildLookupResult where ppr NameNotFound = text "NameNotFound"- ppr (FoundName p n) = text "Found:" <+> ppr p <+> ppr n- ppr (FoundFL fls) = text "FoundFL:" <+> ppr fls- ppr (IncorrectParent p n td ns) = text "IncorrectParent"- <+> hsep [ppr p, ppr n, td, ppr ns]+ ppr (FoundChild p n) = text "Found:" <+> ppr p <+> ppr n+ ppr (IncorrectParent p n ns) = text "IncorrectParent"+ <+> hsep [ppr p, ppr n, ppr ns] lookupSubBndrOcc :: Bool -> Name -- Parent@@ -774,13 +758,12 @@ -- and pick the one with the right parent namep lookupSubBndrOcc warn_if_deprec the_parent doc rdr_name = do res <-- lookupExactOrOrig rdr_name (FoundName NoParent) $+ lookupExactOrOrig rdr_name (FoundChild NoParent . NormalGreName) $ -- This happens for built-in classes, see mod052 for example lookupSubBndrOcc_helper True warn_if_deprec the_parent rdr_name case res of NameNotFound -> return (Left (unknownSubordinateErr doc rdr_name))- FoundName _p n -> return (Right n)- FoundFL fl -> return (Right (flSelector fl))+ FoundChild _p child -> return (Right (greNameMangledName child)) IncorrectParent {} -- See [Mismatched class methods and associated type families] -- in TcInstDecls.@@ -1137,7 +1120,7 @@ lookupGlobalOccRn_base :: RdrName -> RnM (Maybe Name) lookupGlobalOccRn_base rdr_name = runMaybeT . msum . map MaybeT $- [ fmap gre_name <$> lookupGreRn_maybe rdr_name+ [ fmap greMangledName <$> lookupGreRn_maybe rdr_name , listToMaybe <$> lookupQualifiedNameGHCi rdr_name ] -- This test is not expensive, -- and only happens for failed lookups@@ -1153,7 +1136,7 @@ lookupInfoOccRn rdr_name = lookupExactOrOrig rdr_name (:[]) $ do { rdr_env <- getGlobalRdrEnv- ; let ns = map gre_name (lookupGRE_RdrName rdr_name rdr_env)+ ; let ns = map greMangledName (lookupGRE_RdrName rdr_name rdr_env) ; qual_ns <- lookupQualifiedNameGHCi rdr_name ; return (ns ++ (qual_ns `minusList` ns)) } @@ -1176,14 +1159,14 @@ GreNotFound -> return Nothing OneNameMatch gre -> do let wrapper = if isRecFldGRE gre then Right . (:[]) else Left- return $ Just (wrapper (gre_name gre))+ return $ Just (wrapper (greMangledName gre)) MultipleNames gres | all isRecFldGRE gres && overload_ok -> -- Don't record usage for ambiguous selectors -- until we know which is meant- return $ Just (Right (map gre_name gres))+ return $ Just (Right (map greMangledName gres)) MultipleNames gres -> do addNameClashErrRn rdr_name gres- return (Just (Left (gre_name (head gres)))) }+ return (Just (Left (greMangledName (head gres)))) } --------------------------------------------------@@ -1270,7 +1253,7 @@ -- Returning an unbound name here prevents an error -- cascade OneNameMatch gre ->- return (gre_name gre, availFromGRE gre)+ return (greMangledName gre, availFromGRE gre) {-@@ -1327,7 +1310,7 @@ imp_gres = filterOut isLocalGRE gres warnIfDeprecated :: GlobalRdrElt -> RnM ()-warnIfDeprecated gre@(GRE { gre_name = name, gre_imp = iss })+warnIfDeprecated gre@(GRE { gre_imp = iss }) | (imp_spec : _) <- iss = do { dflags <- getDynFlags ; this_mod <- getModule@@ -1343,6 +1326,7 @@ = return () where occ = greOccName gre+ name = greMangledName gre name_mod = ASSERT2( isExternalName name, ppr name ) nameModule name doc = text "The name" <+> quotes (ppr occ) <+> ptext (sLit "is mentioned explicitly") @@ -1363,7 +1347,6 @@ = 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 ParentIs p -> mi_warn_fn (mi_final_exts iface) (nameOccName p)- FldParent { par_is = p } -> mi_warn_fn (mi_final_exts iface) (nameOccName p) NoParent -> Nothing {-@@ -1575,14 +1558,14 @@ filter (\n -> nameSpacesRelated (rdrNameSpace rdr_name) (nameNameSpace n))- $ map gre_name+ $ map greMangledName $ filter isLocalGRE $ globalRdrEnvElts env candidates_msg = candidates names_in_scope- ; case filter (keep_me . gre_name) all_gres of+ ; case filter (keep_me . greMangledName) all_gres of [] | null all_gres -> bale_out_with candidates_msg | otherwise -> bale_out_with local_msg- (gre:_) -> return (Right (gre_name gre)) }+ (gre:_) -> return (Right (greMangledName gre)) } lookup_group bound_names -- Look in the local envt (not top level) = do { mname <- lookupLocalOccRn_maybe rdr_name
compiler/GHC/Rename/Fixity.hs view
@@ -211,7 +211,7 @@ ambigs -> addErr (ambiguous_fixity_err rdr_name ambigs) >> return (Fixity NoSourceText minPrecedence InfixL) - lookup_gre_fixity gre = lookupFixityRn' (gre_name gre) (greOccName gre)+ lookup_gre_fixity gre = lookupFixityRn' (greMangledName gre) (greOccName gre) ambiguous_fixity_err rn ambigs = vcat [ text "Ambiguous fixity for record field" <+> quotes (ppr rn)
compiler/GHC/Rename/HsType.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-} {- (c) The GRASP/AQUA Project, Glasgow University, 1992-1998@@ -11,10 +13,11 @@ -- Type related stuff rnHsType, rnLHsType, rnLHsTypes, rnContext, rnHsKind, rnLHsKind, rnLHsTypeArgs,- rnHsSigType, rnHsWcType,+ rnHsSigType, rnHsWcType, rnHsPatSigTypeBindingVars, HsPatSigTypeScoping(..), rnHsSigWcType, rnHsPatSigType, newTyVarNameRn, rnConDeclFields,+ lookupField, rnLTyVar, rnScaledLHsType,@@ -26,7 +29,7 @@ -- Binding related stuff bindHsOuterTyVarBndrs, bindHsForAllTelescope, bindLHsTyVarBndr, bindLHsTyVarBndrs, WarnUnusedForalls(..),- rnImplicitBndrs, bindSigTyVarsFV, bindHsQTyVars,+ rnImplicitTvOccs, bindSigTyVarsFV, bindHsQTyVars, FreeKiTyVars, extractHsTyRdrTyVars, extractHsTyRdrTyVarsKindVars, extractHsTysRdrTyVars, extractRdrKindSigVars,@@ -39,6 +42,7 @@ import {-# SOURCE #-} GHC.Rename.Splice( rnSpliceType ) +import GHC.Core.TyCo.FVs ( tyCoVarsOfTypeList ) import GHC.Driver.Session import GHC.Hs import GHC.Rename.Env@@ -48,6 +52,7 @@ , checkShadowedRdrNames ) import GHC.Rename.Fixity ( lookupFieldFixityRn, lookupFixityRn , lookupTyFixityRn )+import GHC.Rename.Unbound ( notInScopeErr ) import GHC.Tc.Utils.Monad import GHC.Types.Name.Reader import GHC.Builtin.Names@@ -66,8 +71,10 @@ import GHC.Data.Maybe import qualified GHC.LanguageExtensions as LangExt -import Data.List ( nubBy, partition )-import Control.Monad ( unless, when )+import Data.List+import qualified Data.List.NonEmpty as NE+import Data.List.NonEmpty (NonEmpty(..))+import Control.Monad #include "GhclibHsVersions.h" @@ -153,7 +160,7 @@ implicit_bndrs = case scoping of AlwaysBind -> tv_rdrs NeverBind -> []- ; rnImplicitBndrs Nothing implicit_bndrs $ \ imp_tvs ->+ ; rnImplicitTvOccs Nothing implicit_bndrs $ \ imp_tvs -> do { (nwcs, pat_sig_ty', fvs1) <- rnWcBody ctx nwc_rdrs pat_sig_ty ; let sig_names = HsPSRn { hsps_nwcs = nwcs, hsps_imp_tvs = imp_tvs } sig_ty' = HsPS { hsps_ext = sig_names, hsps_body = pat_sig_ty' }@@ -171,6 +178,57 @@ ; let sig_ty' = HsWC { hswc_ext = wcs, hswc_body = hs_ty' } ; return (sig_ty', fvs) } +-- Similar to rnHsWcType, but rather than requiring free variables in the type to+-- already be in scope, we are going to require them not to be in scope,+-- and we bind them.+rnHsPatSigTypeBindingVars :: HsDocContext+ -> HsPatSigType GhcPs+ -> (HsPatSigType GhcRn -> RnM (r, FreeVars))+ -> RnM (r, FreeVars)+rnHsPatSigTypeBindingVars ctxt sigType thing_inside = case sigType of+ (HsPS { hsps_body = hs_ty }) -> do+ rdr_env <- getLocalRdrEnv+ let (varsInScope, varsNotInScope) =+ partition (inScope rdr_env . unLoc) (extractHsTyRdrTyVars hs_ty)+ -- TODO: Resolve and remove this comment.+ -- This next bit is in some contention. The original proposal #126+ -- (https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0126-type-applications-in-patterns.rst)+ -- says that in-scope variables are fine here: don't bind them, just use+ -- the existing vars, like in type signatures. An amendment #291+ -- (https://github.com/ghc-proposals/ghc-proposals/pull/291) says that the+ -- use of an in-scope variable should *shadow* an in-scope tyvar, like in+ -- terms. In an effort to make forward progress, the current implementation+ -- just rejects any use of an in-scope variable, meaning GHC will accept+ -- a subset of programs common to both variants. If this comment still exists+ -- in mid-to-late 2021 or thereafter, we have done a poor job on following+ -- up on this point.+ -- Example:+ -- f :: forall a. ...+ -- f (MkT @a ...) = ...+ -- Should the inner `a` refer to the outer one? shadow it? We are, as yet, undecided,+ -- so we currently reject.+ when (not (null varsInScope)) $+ addErr $+ vcat+ [ text "Type variable" <> plural varsInScope+ <+> hcat (punctuate (text ",") (map (quotes . ppr) varsInScope))+ <+> isOrAre varsInScope+ <+> text "already in scope."+ , text "Type applications in patterns must bind fresh variables, without shadowing."+ ]+ (wcVars, ibVars) <- partition_nwcs varsNotInScope+ rnImplicitTvBndrs ctxt Nothing ibVars $ \ ibVars' -> do+ (wcVars', hs_ty', fvs) <- rnWcBody ctxt wcVars hs_ty+ let sig_ty = HsPS+ { hsps_body = hs_ty'+ , hsps_ext = HsPSRn+ { hsps_nwcs = wcVars'+ , hsps_imp_tvs = ibVars'+ }+ }+ (res, fvs') <- thing_inside sig_ty+ return (res, fvs `plusFV` fvs')+ rnWcBody :: HsDocContext -> [Located RdrName] -> LHsType GhcPs -> RnM ([Name], LHsType GhcRn, FreeVars) rnWcBody ctxt nwc_rdrs hs_ty@@ -322,17 +380,20 @@ where env = mkTyKiEnv ctx level RnTypeBody -rnImplicitBndrs :: Maybe assoc- -- ^ @'Just' _@ => an associated type decl- -> FreeKiTyVars- -- ^ Surface-syntax free vars that we will implicitly bind.- -- May have duplicates, which are removed here.- -> ([Name] -> RnM (a, FreeVars))- -> RnM (a, FreeVars)-rnImplicitBndrs mb_assoc implicit_vs_with_dups thing_inside+-- | Create new renamed type variables corresponding to source-level ones.+-- Duplicates are permitted, but will be removed. This is intended especially for+-- the case of handling the implicitly bound free variables of a type signature.+rnImplicitTvOccs :: Maybe assoc+ -- ^ @'Just' _@ => an associated type decl+ -> FreeKiTyVars+ -- ^ Surface-syntax free vars that we will implicitly bind.+ -- May have duplicates, which are removed here.+ -> ([Name] -> RnM (a, FreeVars))+ -> RnM (a, FreeVars)+rnImplicitTvOccs mb_assoc implicit_vs_with_dups thing_inside = do { let implicit_vs = nubL implicit_vs_with_dups - ; traceRn "rnImplicitBndrs" $+ ; traceRn "rnImplicitTvOccs" $ vcat [ ppr implicit_vs_with_dups, ppr implicit_vs ] -- Use the currently set SrcSpan as the new source location for each Name.@@ -346,7 +407,7 @@ {- Note [Source locations for implicitly bound type variables] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When bringing implicitly bound type variables into scope (in rnImplicitBndrs),+When bringing implicitly bound type variables into scope (in rnImplicitTvOccs), we do something peculiar: we drop the original SrcSpan attached to each variable and replace it with the currently set SrcSpan. Moreover, this new SrcSpan is usually /less/ precise than the original one, and that's OK. To see@@ -366,6 +427,31 @@ sites. This is less precise, but more accurate. -} +-- | Create fresh type variables for binders, disallowing multiple occurrences of the same variable. Similar to `rnImplicitTvOccs` except that duplicate occurrences will+-- result in an error, and the source locations of the variables are not adjusted, as these variable occurrences are themselves the binding sites for the type variables,+-- rather than the variables being implicitly bound by a signature.+rnImplicitTvBndrs :: HsDocContext+ -> Maybe assoc+ -- ^ @'Just' _@ => an associated type decl+ -> FreeKiTyVars+ -- ^ Surface-syntax free vars that we will implicitly bind.+ -- Duplicate variables will cause a compile-time error regarding repeated bindings.+ -> ([Name] -> RnM (a, FreeVars))+ -> RnM (a, FreeVars)+rnImplicitTvBndrs ctx mb_assoc implicit_vs_with_dups thing_inside+ = do { implicit_vs <- forM (NE.groupBy eqLocated $ sortBy cmpLocated $ implicit_vs_with_dups) $ \case+ (x :| []) -> return x+ (x :| _) -> do addErr $ text "Variable" <+> text "`" <> ppr x <> text "'" <+> text "would be bound multiple times by" <+> pprHsDocContext ctx <> text "."+ return x++ ; traceRn "rnImplicitTvBndrs" $+ vcat [ ppr implicit_vs_with_dups, ppr implicit_vs ]++ ; vars <- mapM (newTyVarNameRn mb_assoc) implicit_vs++ ; bindLocalNamesFV vars $+ thing_inside vars }+ {- ****************************************************** * * LHsType and HsType@@ -634,11 +720,21 @@ = do { (ty', fvs) <- rnLHsTyKi env ty ; return (HsDocTy noExtField ty' haddock_doc, fvs) } -rnHsTyKi _ (XHsType (NHsCoreTy ty))- = return (XHsType (NHsCoreTy ty), emptyFVs)- -- The emptyFVs probably isn't quite right- -- but I don't think it matters+-- See Note [Renaming HsCoreTys]+rnHsTyKi env (XHsType ty)+ = do mapM_ (check_in_scope . nameRdrName) fvs_list+ return (XHsType ty, fvs)+ where+ fvs_list = map getName $ tyCoVarsOfTypeList ty+ fvs = mkFVs fvs_list + check_in_scope :: RdrName -> RnM ()+ check_in_scope rdr_name = do+ mb_name <- lookupLocalOccRn_maybe rdr_name+ when (isNothing mb_name) $+ addErr $ withHsDocContext (rtke_ctxt env) $+ notInScopeErr rdr_name+ rnHsTyKi env ty@(HsExplicitListTy _ ip tys) = do { data_kinds <- xoptM LangExt.DataKinds ; unless data_kinds (addErr (dataKindsErr env ty))@@ -661,6 +757,39 @@ rnHsArrow env (HsExplicitMult u p) = (\(mult, fvs) -> (HsExplicitMult u mult, fvs)) <$> rnLHsTyKi env p +{-+Note [Renaming HsCoreTys]+~~~~~~~~~~~~~~~~~~~~~~~~~+HsCoreTy is an escape hatch that allows embedding Core Types in HsTypes.+As such, there's not much to be done in order to rename an HsCoreTy,+since it's already been renamed to some extent. However, in an attempt to+detect ill-formed HsCoreTys, the renamer checks to see if all free type+variables in an HsCoreTy are in scope. To see why this can matter, consider+this example from #18914:++ type T f = forall a. f a++ class C f where+ m :: T f++ newtype N f a = MkN (f a)+ deriving C++Because of #18914, a previous GHC would generate the following code:++ instance C f => C (N f) where+ m :: T (N f)+ m = coerce @(f a) -- The type within @(...) is an HsCoreTy+ @(N f a) -- So is this+ (m @f)++There are two HsCoreTys in play—(f a) and (N f a)—both of which have+`f` and `a` as free type variables. The `f` is in scope from the instance head,+but `a` is completely unbound, which is what led to #18914. To avoid this sort+of mistake going forward, the renamer will now detect that `a` is unbound and+throw an error accordingly.+-}+ -------------- rnTyVar :: RnTyKiEnv -> RdrName -> RnM Name rnTyVar env rdr_name@@ -836,12 +965,12 @@ , text "body_remaining" <+> ppr body_remaining ] - ; rnImplicitBndrs mb_assoc implicit_kvs $ \ implicit_kv_nms' ->+ ; rnImplicitTvOccs mb_assoc implicit_kvs $ \ implicit_kv_nms' -> bindLHsTyVarBndrs doc NoWarnUnusedForalls mb_assoc hs_tv_bndrs $ \ rn_bndrs -> -- This is the only call site for bindLHsTyVarBndrs where we pass -- NoWarnUnusedForalls, which suppresses -Wunused-foralls warnings. -- See Note [Suppress -Wunused-foralls when binding LHsQTyVars].- do { let -- The SrcSpan that rnImplicitBndrs will attach to each Name will+ do { let -- The SrcSpan that rnImplicitTvOccs will attach to each Name will -- span the entire declaration to which the LHsQTyVars belongs, -- which will be reflected in warning and error messages. We can -- be a little more precise than that by pointing to the location@@ -895,7 +1024,7 @@ bring Names into scope. * bndr_kv_occs, body_kv_occs, and implicit_kvs can contain duplicates. All- duplicate occurrences are removed when we bind them with rnImplicitBndrs.+ duplicate occurrences are removed when we bind them with rnImplicitTvOccs. Finally, you may wonder why filterFreeVarsToBind removes in-scope variables from bndr/body_kv_occs. How can anything be in scope? Answer:@@ -999,7 +1128,7 @@ bindHsOuterTyVarBndrs doc mb_cls implicit_vars outer_bndrs thing_inside = case outer_bndrs of HsOuterImplicit{} ->- rnImplicitBndrs mb_cls implicit_vars $ \implicit_vars' ->+ rnImplicitTvOccs mb_cls implicit_vars $ \implicit_vars' -> thing_inside $ HsOuterImplicit { hso_ximplicit = implicit_vars' } HsOuterExplicit{hso_bndrs = exp_bndrs} -> -- Note: If we pass mb_cls instead of Nothing below, bindLHsTyVarBndrs@@ -1119,17 +1248,17 @@ rnField :: FastStringEnv FieldLabel -> RnTyKiEnv -> LConDeclField GhcPs -> RnM (LConDeclField GhcRn, FreeVars) rnField fl_env env (L l (ConDeclField _ names ty haddock_doc))- = do { let new_names = map (fmap lookupField) names+ = do { let new_names = map (fmap (lookupField fl_env)) names ; (new_ty, fvs) <- rnLHsTyKi env ty ; return (L l (ConDeclField noExtField new_names new_ty haddock_doc) , fvs) }++lookupField :: FastStringEnv FieldLabel -> FieldOcc GhcPs -> FieldOcc GhcRn+lookupField fl_env (FieldOcc _ (L lr rdr)) =+ FieldOcc (flSelector fl) (L lr rdr) where- lookupField :: FieldOcc GhcPs -> FieldOcc GhcRn- lookupField (FieldOcc _ (L lr rdr)) =- FieldOcc (flSelector fl) (L lr rdr)- where- lbl = occNameFS $ rdrNameOcc rdr- fl = expectJust "rnField" $ lookupFsEnv fl_env lbl+ lbl = occNameFS $ rdrNameOcc rdr+ fl = expectJust "lookupField" $ lookupFsEnv fl_env lbl {- ************************************************************************@@ -1544,7 +1673,7 @@ It is common for lists of free type variables to contain duplicates. For example, in `f :: a -> a`, the free type variable list is [a, a]. When these-implicitly bound variables are brought into scope (with rnImplicitBndrs),+implicitly bound variables are brought into scope (with rnImplicitTvOccs), duplicates are removed with nubL. Note [Ordering of implicit variables]@@ -1880,7 +2009,7 @@ -- Deletes duplicates in a list of Located things. This is used to: -- -- * Delete duplicate occurrences of implicitly bound type/kind variables when--- bringing them into scope (in rnImplicitBndrs).+-- bringing them into scope (in rnImplicitTvOccs). -- -- * Delete duplicate occurrences of named wildcards (in rn_hs_sig_wc_type and -- rnHsWcType).
compiler/GHC/Rename/Module.hs view
@@ -60,7 +60,7 @@ import GHC.Driver.Session import GHC.Utils.Misc ( debugIsOn, lengthExceeds, partitionWith ) import GHC.Utils.Panic-import GHC.Driver.Env ( HscEnv(..))+import GHC.Driver.Env ( HscEnv(..), hsc_home_unit) import GHC.Data.List.SetOps ( findDupsEq, removeDups, equivClasses ) import GHC.Data.Graph.Directed ( SCC, flattenSCC, flattenSCCs, Node(..) , stronglyConnCompFromEdgedVerticesUniq )@@ -661,12 +661,13 @@ rnFamEqn :: HsDocContext -> AssocTyFamInfo -> FreeKiTyVars- -- ^ Kind variables from the equation's RHS to be implicitly bound- -- if no explicit forall.+ -- ^ Additional kind variables to implicitly bind if there is no+ -- explicit forall. (See the comments on @all_imp_vars@ below for a+ -- more detailed explanation.) -> FamEqn GhcPs rhs -> (HsDocContext -> rhs -> RnM (rhs', FreeVars)) -> RnM (FamEqn GhcRn rhs', FreeVars)-rnFamEqn doc atfi rhs_kvars+rnFamEqn doc atfi extra_kvars (FamEqn { feqn_tycon = tycon , feqn_bndrs = outer_bndrs , feqn_pats = pats@@ -679,15 +680,19 @@ -- Note [forall-or-nothing rule] in GHC.Hs.Type), which means -- ignoring: --- -- - pat_kity_vars_with_dups, the variables mentioned in the LHS of- -- the equation, and- -- - rhs_kvars, the kind variables mentioned in an outermost kind- -- signature on the RHS of the equation. (See- -- Note [Implicit quantification in type synonyms] in- -- GHC.Rename.HsType for why these are implicitly quantified in the- -- absence of an explicit forall).+ -- - pat_kity_vars, the free variables mentioned in the type patterns+ -- on the LHS of the equation, and+ -- - extra_kvars, which is one of the following:+ -- * For type family instances, extra_kvars are the free kind+ -- variables mentioned in an outermost kind signature on the RHS+ -- of the equation.+ -- (See Note [Implicit quantification in type synonyms] in+ -- GHC.Rename.HsType.)+ -- * For data family instances, extra_kvars are the free kind+ -- variables mentioned in the explicit return kind, if one is+ -- provided. (e.g., the `k` in `data instance T :: k -> Type`). --- -- For example:+ -- Some examples: -- -- @ -- type family F a b@@ -695,8 +700,20 @@ -- -- all_imp_vars = [] -- type instance F [(a, b)] c = a -> b -> c -- -- all_imp_vars = [a, b, c]+ --+ -- type family G :: Maybe a+ -- type instance forall a. G = (Nothing :: Maybe a)+ -- -- all_imp_vars = []+ -- type instance G = (Nothing :: Maybe a)+ -- -- all_imp_vars = [a]+ --+ -- data family H :: k -> Type+ -- data instance forall k. H :: k -> Type where ...+ -- -- all_imp_vars = []+ -- data instance H :: k -> Type where ...+ -- -- all_imp_vars = [k] -- @- ; let all_imp_vars = pat_kity_vars_with_dups ++ rhs_kvars+ ; let all_imp_vars = pat_kity_vars ++ extra_kvars ; bindHsOuterTyVarBndrs doc mb_cls all_imp_vars outer_bndrs $ \rn_outer_bndrs -> do { (pats', pat_fvs) <- rnLHsTypeArgs (FamPatCtx tycon) pats@@ -714,8 +731,7 @@ rn_outer_bndrs groups :: [NonEmpty (Located RdrName)]- groups = equivClasses cmpLocated $- pat_kity_vars_with_dups+ groups = equivClasses cmpLocated pat_kity_vars ; nms_dups <- mapM (lookupOccRn . unLoc) $ [ tv | (tv :| (_:_)) <- groups ] -- Add to the used variables@@ -725,10 +741,24 @@ -- of the instance decl. See -- Note [Unused type variables in family instances] ; let nms_used = extendNameSetList rhs_fvs $- inst_tvs ++ nms_dups+ nms_dups {- (a) -} ++ inst_head_tvs {- (b) -} all_nms = hsOuterTyVarNames rn_outer_bndrs' ; warnUnusedTypePatterns all_nms nms_used + -- For associated family instances, if a type variable from the+ -- parent instance declaration is mentioned on the RHS of the+ -- associated family instance but not bound on the LHS, then reject+ -- that type variable as being out of scope.+ -- See Note [Renaming associated types]+ ; let lhs_bound_vars = extendNameSetList pat_fvs all_nms+ improperly_scoped cls_tkv =+ cls_tkv `elemNameSet` rhs_fvs+ -- Mentioned on the RHS...+ && not (cls_tkv `elemNameSet` lhs_bound_vars)+ -- ...but not bound on the LHS.+ bad_tvs = filter improperly_scoped inst_head_tvs+ ; unless (null bad_tvs) (badAssocRhs bad_tvs)+ ; let eqn_fvs = rhs_fvs `plusFV` pat_fvs -- See Note [Type family equations and occurrences] all_fvs = case atfi of@@ -754,12 +784,12 @@ -- The type variables from the instance head, if we are dealing with an -- associated type family instance.- inst_tvs = case atfi of- NonAssocTyFamEqn _ -> []- AssocTyFamDeflt _ -> []- AssocTyFamInst _ inst_tvs -> inst_tvs+ inst_head_tvs = case atfi of+ NonAssocTyFamEqn _ -> []+ AssocTyFamDeflt _ -> []+ AssocTyFamInst _ inst_head_tvs -> inst_head_tvs - pat_kity_vars_with_dups = extractHsTyArgRdrKiTyVars pats+ pat_kity_vars = extractHsTyArgRdrKiTyVars pats -- It is crucial that extractHsTyArgRdrKiTyVars return -- duplicate occurrences, since they're needed to help -- determine unused binders on the LHS.@@ -769,11 +799,18 @@ -- -- type instance F a b c = Either a b -- ^^^^^- lhs_loc = case map lhsTypeArgSrcSpan pats ++ map getLoc rhs_kvars of+ lhs_loc = case map lhsTypeArgSrcSpan pats ++ map getLoc extra_kvars of [] -> panic "rnFamEqn.lhs_loc" [loc] -> loc (loc:locs) -> loc `combineSrcSpans` last locs + badAssocRhs :: [Name] -> RnM ()+ badAssocRhs ns+ = addErr (hang (text "The RHS of an associated type declaration mentions"+ <+> text "out-of-scope variable" <> plural ns+ <+> pprWithCommas (quotes . ppr) ns)+ 2 (text "All such variables must be bound on the LHS"))+ rnTyFamInstDecl :: AssocTyFamInfo -> TyFamInstDecl GhcPs -> RnM (TyFamInstDecl GhcRn, FreeVars)@@ -829,9 +866,9 @@ -> TyFamInstEqn GhcPs -> RnM (TyFamInstEqn GhcRn, FreeVars) rnTyFamInstEqn atfi eqn@(FamEqn { feqn_tycon = tycon, feqn_rhs = rhs })- = rnFamEqn (TySynCtx tycon) atfi rhs_kvs eqn rnTySyn+ = rnFamEqn (TySynCtx tycon) atfi extra_kvs eqn rnTySyn where- rhs_kvs = extractHsTyRdrTyVarsKindVars rhs+ extra_kvs = extractHsTyRdrTyVarsKindVars rhs rnTyFamDefltDecl :: Name -> TyFamDefltDecl GhcPs@@ -844,9 +881,9 @@ rnDataFamInstDecl atfi (DataFamInstDecl { dfid_eqn = eqn@(FamEqn { feqn_tycon = tycon , feqn_rhs = rhs })})- = do { let rhs_kvs = extractDataDefnKindVars rhs+ = do { let extra_kvs = extractDataDefnKindVars rhs ; (eqn', fvs) <-- rnFamEqn (TyDataCtx tycon) atfi rhs_kvs eqn rnDataDefn+ rnFamEqn (TyDataCtx tycon) atfi extra_kvs eqn rnDataDefn ; return (DataFamInstDecl { dfid_eqn = eqn' }, fvs) } -- Renaming of the associated types in instances.@@ -927,59 +964,132 @@ Note [Renaming associated types] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Check that the RHS of the decl mentions only type variables that are explicitly-bound on the LHS. For example, this is not ok- class C a b where- type F a x :: *- instance C (p,q) r where- type F (p,q) x = (x, r) -- BAD: mentions 'r'-c.f. #5515+When renaming a type/data family instance, be it top-level or associated with+a class, we must check that all of the type variables mentioned on the RHS are+properly scoped. Specifically, the rule is this: -Kind variables, on the other hand, are allowed to be implicitly or explicitly-bound. As examples, this (#9574) is acceptable:- class Funct f where- type Codomain f :: *- instance Funct ('KProxy :: KProxy o) where- -- o is implicitly bound by the kind signature- -- of the LHS type pattern ('KProxy)- type Codomain 'KProxy = NatTr (Proxy :: o -> *)-And this (#14131) is also acceptable:- data family Nat :: k -> k -> *- -- k is implicitly bound by an invisible kind pattern- newtype instance Nat :: (k -> *) -> (k -> *) -> * where- Nat :: (forall xx. f xx -> g xx) -> Nat f g-We could choose to disallow this, but then associated type families would not-be able to be as expressive as top-level type synonyms. For example, this type-synonym definition is allowed:- type T = (Nothing :: Maybe a)-So for parity with type synonyms, we also allow:- type family T :: Maybe a- type instance T = (Nothing :: Maybe a)+ Every variable mentioned on the RHS of a type instance declaration+ (whether associated or not) must be either+ * Mentioned on the LHS, or+ * Mentioned in an outermost kind signature on the RHS+ (see Note [Implicit quantification in type synonyms]) -All this applies only for *instance* declarations. In *class*-declarations there is no RHS to worry about, and the class variables-can all be in scope (#5862):+Here is a simple example of something we should reject:++ class C a b where+ type F a x+ instance C Int Bool where+ type F Int x = z++Here, `z` is mentioned on the RHS of the associated instance without being+mentioned on the LHS, nor is `z` mentioned in an outermost kind signature. The+renamer will reject `z` as being out of scope without much fuss.++Things get slightly trickier when the instance header itself binds type+variables. Consider this example (adapted from #5515):++ instance C (p,q) z where+ type F (p,q) x = (x, z)++According to the rule above, this instance is improperly scoped. However, due+to the way GHC's renamer works, `z` is /technically/ in scope, as GHC will+always bring type variables from an instance header into scope over the+associated type family instances. As a result, the renamer won't simply reject+the `z` as being out of scope (like it would for the `type F Int x = z`+example) unless further action is taken. It is important to reject this sort of+thing in the renamer, because if it is allowed to make it through to the+typechecker, unexpected shenanigans can occur (see #18021 for examples).++To prevent these sorts of shenanigans, we reject programs like the one above+with an extra validity check in rnFamEqn. For each type variable bound in the+parent instance head, we check if it is mentioned on the RHS of the associated+family instance but not bound on the LHS. If any of the instance-head-bound+variables meet these criteria, we throw an error.+(See rnFamEqn.improperly_scoped for how this is implemented.)++Some additional wrinkles:++* This Note only applies to *instance* declarations. In *class* declarations+ there is no RHS to worry about, and the class variables can all be in scope+ (#5862):+ class Category (x :: k -> k -> *) where type Ob x :: k -> Constraint id :: Ob x a => x a a (.) :: (Ob x a, Ob x b, Ob x c) => x b c -> x a b -> x a c-Here 'k' is in scope in the kind signature, just like 'x'. -Although type family equations can bind type variables with explicit foralls,-it need not be the case that all variables that appear on the RHS must be bound-by a forall. For instance, the following is acceptable:+ Here 'k' is in scope in the kind signature, just like 'x'. - class C a where- type T a b- instance C (Maybe a) where- type forall b. T (Maybe a) b = Either a b+* Although type family equations can bind type variables with explicit foralls,+ it need not be the case that all variables that appear on the RHS must be+ bound by a forall. For instance, the following is acceptable: -Even though `a` is not bound by the forall, this is still accepted because `a`-was previously bound by the `instance C (Maybe a)` part. (see #16116).+ class C4 a where+ type T4 a b+ instance C4 (Maybe a) where+ type forall b. T4 (Maybe a) b = Either a b -In each case, the function which detects improperly bound variables on the RHS-is GHC.Tc.Validity.checkValidFamPats.+ Even though `a` is not bound by the forall, this is still accepted because `a`+ was previously bound by the `instance C4 (Maybe a)` part. (see #16116). +* In addition to the validity check in rnFamEqn.improperly_scoped, there is an+ additional check in GHC.Tc.Validity.checkFamPatBinders that checks each family+ instance equation for type variables used on the RHS but not bound on the+ LHS. This is not made redundant by rmFamEqn.improperly_scoped, as there are+ programs that each check will reject that the other check will not catch:++ - checkValidFamPats is used on all forms of family instances, whereas+ rmFamEqn.improperly_scoped only checks associated family instances. Since+ checkFamPatBinders occurs after typechecking, it can catch programs that+ introduce dodgy scoping by way of type synonyms (see #7536), which is+ impractical to accomplish in the renamer.+ - rnFamEqn.improperly_scoped catches some programs that, if allowed to escape+ the renamer, would accidentally be accepted by the typechecker. Here is one+ such program (#18021):++ class C5 a where+ data family D a++ instance forall a. C5 Int where+ data instance D Int = MkD a++ If this is not rejected in the renamer, the typechecker would treat this+ program as though the `a` were existentially quantified, like so:++ data instance D Int = forall a. MkD a++ This is likely not what the user intended!++ Here is another such program (#9574):++ class Funct f where+ type Codomain f+ instance Funct ('KProxy :: KProxy o) where+ type Codomain 'KProxy = NatTr (Proxy :: o -> Type)++ Where:++ data Proxy (a :: k) = Proxy+ data KProxy (t :: Type) = KProxy+ data NatTr (c :: o -> Type)++ Note that the `o` in the `Codomain 'KProxy` instance should be considered+ improperly scoped. It does not meet the criteria for being explicitly+ quantified, as it is not mentioned by name on the LHS, nor does it meet the+ criteria for being implicitly quantified, as it is used in a RHS kind+ signature that is not outermost (see Note [Implicit quantification in type+ synonyms]). However, `o` /is/ bound by the instance header, so if this+ program is not rejected by the renamer, the typechecker would treat it as+ though you had written this:++ instance Funct ('KProxy :: KProxy o) where+ type Codomain ('KProxy @o) = NatTr (Proxy :: o -> Type)++ Although this is a valid program, it's probably a stretch too far to turn+ `type Codomain 'KProxy = ...` into `type Codomain ('KProxy @o) = ...` here.+ If the user really wants the latter, it is simple enough to communicate+ their intent by mentioning `o` on the LHS by name.+ Note [Type family equations and occurrences] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In most data/type family equations, the type family name used in the equation@@ -1503,7 +1613,6 @@ = case lookupGRE_Name rdr_env n of Just gre -> case gre_par gre of ParentIs { par_is = p } -> p- FldParent { par_is = p } -> p _ -> n Nothing -> n @@ -2234,9 +2343,9 @@ -> HsDocContext -> HsConDeclH98Details GhcPs -> RnM (HsConDeclH98Details GhcRn, FreeVars)-rnConDeclH98Details _ doc (PrefixCon tys)+rnConDeclH98Details _ doc (PrefixCon _ tys) = do { (new_tys, fvs) <- mapFvRn (rnScaledLHsType doc) tys- ; return (PrefixCon new_tys, fvs) }+ ; return (PrefixCon noTypeArgs new_tys, fvs) } rnConDeclH98Details _ doc (InfixCon ty1 ty2) = do { (new_ty1, fvs1) <- rnScaledLHsType doc ty1 ; (new_ty2, fvs2) <- rnScaledLHsType doc ty2@@ -2279,7 +2388,8 @@ names_with_fls <- new_ps val_decls ; let pat_syn_bndrs = concat [ name: map flSelector fields | (name, fields) <- names_with_fls ]- ; let avails = map avail pat_syn_bndrs+ ; let avails = map avail (map fst names_with_fls)+ ++ map availField (concatMap snd names_with_fls) ; (gbl_env, lcl_env) <- extendGlobalRdrEnvRn avails local_fix_env ; let field_env' = extendNameEnvList (tcg_field_env gbl_env) names_with_fls@@ -2298,11 +2408,9 @@ , psb_args = RecCon as }))) <- bind = do bnd_name <- newTopSrcBinder (L bind_loc n)- let rnames = map recordPatSynSelectorId as- mkFieldOcc :: Located RdrName -> LFieldOcc GhcPs- mkFieldOcc (L l name) = L l (FieldOcc noExtField (L l name))- field_occs = map mkFieldOcc rnames- flds <- mapM (newRecordSelector False [bnd_name]) field_occs+ let field_occs = map ((\ f -> L (getLoc (rdrNameFieldOcc f)) f) . recordPatSynField) as+ overload_ok <- xoptM LangExt.DuplicateRecordFields+ flds <- mapM (newRecordSelector overload_ok [bnd_name]) field_occs return ((bnd_name, flds): names) | L bind_loc (PatSynBind _ (PSB { psb_id = L _ n})) <- bind = do
compiler/GHC/Rename/Names.hs view
@@ -84,7 +84,7 @@ import GHC.Data.FastString.Env import Control.Monad-import Data.Either ( partitionEithers, isRight, rights )+import Data.Either ( partitionEithers ) import Data.Map ( Map ) import qualified Data.Map as Map import Data.Ord ( comparing )@@ -645,7 +645,7 @@ | otherwise = fix_env where- name = gre_name gre+ name = greMangledName gre occ = greOccName gre new_gres :: [GlobalRdrElt] -- New LocalDef GREs, derived from avails@@ -663,14 +663,72 @@ | otherwise = return (extendGlobalRdrEnv env gre) where- occ = greOccName gre- dups = filter isDupGRE (lookupGlobalRdrEnv env occ)- -- Duplicate GREs are those defined locally with the same OccName,- -- except cases where *both* GREs are DuplicateRecordFields (#17965).+ -- See Note [Reporting duplicate local declarations]+ dups = filter isDupGRE (lookupGlobalRdrEnv env (greOccName gre)) isDupGRE gre' = isLocalGRE gre'- && not (isOverloadedRecFldGRE gre && isOverloadedRecFldGRE gre')+ && (not (isOverloadedRecFldGRE gre && isOverloadedRecFldGRE gre')+ || (gre_name gre == gre_name gre')) +{-+Note [Reporting duplicate local declarations]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In general, a single module may not define the same OccName multiple times. This+is checked in extendGlobalRdrEnvRn: when adding a new locally-defined GRE to the+GlobalRdrEnv we report an error if there are already duplicates in the+environment. This establishes INVARIANT 1 of the GlobalRdrEnv, which says that+for a given OccName, all the GlobalRdrElts to which it maps must have distinct+'gre_name's. +For example, the following will be rejected:++ f x = x+ g x = x+ f x = x -- Duplicate!++Under what conditions will a GRE that exists already count as a duplicate of the+LocalDef GRE being added?++* It must also be a LocalDef: the programmer is allowed to make a new local+ definition that clashes with an imported one (although attempting to refer to+ either may lead to ambiguity errors at use sites). For example, the following+ definition is allowed:++ import M (f)+ f x = x++* When DuplicateRecordFields is enabled, the same field label may be defined in+ multiple records. For example, this is allowed:++ {-# LANGUAGE DuplicateRecordFields #-}+ data S1 = MkS1 { f :: Int }+ data S2 = MkS2 { f :: Int }++ Even though both fields have the same OccName, this does not violate INVARIANT+ 1, because the fields have distinct selector names, which form part of the+ gre_name (see Note [GreNames] in GHC.Types.Name.Reader).++* However, we must be careful to reject the following (#9156):++ {-# LANGUAGE DuplicateRecordFields #-}+ data T = MkT { f :: Int, f :: Int } -- Duplicate!++ In this case, both 'gre_name's are the same (because the fields belong to the+ same type), and adding them both to the environment would be a violation of+ INVARIANT 1. Thus isDupGRE checks whether both GREs have the same gre_name.++* We also reject attempts to define a field and a non-field with the same+ OccName (#17965):++ {-# LANGUAGE DuplicateRecordFields #-}+ f x = x+ data T = MkT { f :: Int}++ In principle this could be supported, but the current "specification" of+ DuplicateRecordFields does not allow it. Thus isDupGRE checks that *both* GREs+ being compared are record fields.+-}++ {- ********************************************************************* * * getLocalDeclBindersd@ returns the names for an HsDecl@@ -760,7 +818,7 @@ ; let fld_env = case unLoc tc_decl of DataDecl { tcdDataDefn = d } -> mk_fld_env d names flds' _ -> []- ; return (AvailTC main_name names flds', fld_env) }+ ; return (availTC main_name names flds', fld_env) } -- Calculate the mapping from constructor names to fields, which@@ -835,7 +893,7 @@ ; let (bndrs, flds) = hsDataFamInstBinders dfid ; sub_names <- mapM newTopSrcBinder bndrs ; flds' <- mapM (newRecordSelector overload_ok sub_names) flds- ; let avail = AvailTC (unLoc main_name) sub_names flds'+ ; let avail = availTC (unLoc main_name) sub_names flds' -- main_name is not bound here! fld_env = mk_fld_env (feqn_rhs ti_decl) sub_names flds' ; return (avail, fld_env) }@@ -848,10 +906,12 @@ newRecordSelector _ [] _ = error "newRecordSelector: datatype has no constructors!" newRecordSelector overload_ok (dc:_) (L loc (FieldOcc _ (L _ fld))) = do { selName <- newTopSrcBinder $ L loc $ field- ; return $ qualFieldLbl { flSelector = selName } }+ ; return $ FieldLabel { flLabel = fieldLabelString+ , flIsOverloaded = overload_ok+ , flSelector = selName } } where- fieldOccName = occNameFS $ rdrNameOcc fld- qualFieldLbl = mkFieldLabelOccs fieldOccName (nameOccName dc) overload_ok+ fieldLabelString = occNameFS $ rdrNameOcc fld+ selOccName = fieldSelectorOccName fieldLabelString (nameOccName dc) overload_ok field | isExact fld = fld -- use an Exact RdrName as is to preserve the bindings -- of an already renamer-resolved field and its use@@ -859,7 +919,7 @@ -- selectors in Template Haskell. See Note [Binders in -- Template Haskell] in "GHC.ThToHs" and Note [Looking up -- Exact RdrNames] in "GHC.Rename.Env".- | otherwise = mkRdrUnqual (flSelector qualFieldLbl)+ | otherwise = mkRdrUnqual selOccName {- Note [Looking up family names in family instances]@@ -892,9 +952,12 @@ Note [Dealing with imports] ~~~~~~~~~~~~~~~~~~~~~~~~~~~ For import M( ies ), we take the mi_exports of M, and make- imp_occ_env :: OccEnv (Name, AvailInfo, Maybe Name)-One entry for each Name that M exports; the AvailInfo is the-AvailInfo exported from M that exports that Name.+ imp_occ_env :: OccEnv (NameEnv (GreName, AvailInfo, Maybe Name))+One entry for each OccName that M exports, mapping each corresponding Name to+its GreName, the AvailInfo exported from M that exports that Name, and+optionally a Name for an associated type's parent class. (Typically there will+be a single Name in the NameEnv, but see Note [Importing DuplicateRecordFields]+for why we may need more than one.) The situation is made more complicated by associated types. E.g. module M where@@ -906,7 +969,7 @@ Notice that T appears *twice*, once as a child and once as a parent. From this list we construct a raw list including T -> (T, T( T1, T2, T3 ), Nothing)- T -> (C, C( C, T ), Nothing)+ T -> (T, C( C, T ), Nothing) and we combine these (in function 'combine' in 'imp_occ_env' in 'filterImports') to get T -> (T, T(T,T1,T2,T3), Just C)@@ -922,6 +985,57 @@ Note that the imp_occ_env will have entries for data constructors too, although we never look up data constructors.++Note [Importing PatternSynonyms]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+As described in Note [Dealing with imports], associated types can lead to the+same Name appearing twice, both as a child and once as a parent, when+constructing the imp_occ_env. The same thing can happen with pattern synonyms+if they are exported bundled with a type.++A simplified example, based on #11959:++ {-# LANGUAGE PatternSynonyms #-}+ module M (T(P), pattern P) where -- Duplicate export warning, but allowed+ data T = MkT+ pattern P = MkT++Here we have T(P) and P in export_avails, and construct both+ P -> (P, P, Nothing)+ P -> (P, T(P), Nothing)+which are 'combine'd to leave+ P -> (P, T(P), Nothing)+i.e. we simply discard the non-bundled Avail.++Note [Importing DuplicateRecordFields]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In filterImports, another complicating factor is DuplicateRecordFields.+Suppose we have:++ {-# LANGUAGE DuplicateRecordFields #-}+ module M (S(foo), T(foo)) where+ data S = MkS { foo :: Int }+ data T = mkT { foo :: Int }++ module N where+ import M (foo) -- this is an ambiguity error (A)+ import M (S(foo)) -- this is allowed (B)++Here M exports the OccName 'foo' twice, so we get an imp_occ_env where 'foo'+maps to a NameEnv containing an entry for each of the two mangled field selector+names (see Note [FieldLabel] in GHC.Types.FieldLabel).++ foo -> [ $sel:foo:MkS -> (foo, S(foo), Nothing)+ , $sel:foo:MKT -> (foo, T(foo), Nothing)+ ]++Then when we look up 'foo' in lookup_name for case (A) we get both entries and+hence report an ambiguity error. Whereas in case (B) we reach the lookup_ie+case for IEThingWith, which looks up 'S' and then finds the unique 'foo' amongst+its children.++See T16745 for a test of this.+ -} filterImports@@ -958,30 +1072,46 @@ all_avails = mi_exports iface -- See Note [Dealing with imports]- imp_occ_env :: OccEnv (Name, -- the name- AvailInfo, -- the export item providing the name- Maybe Name) -- the parent of associated types- imp_occ_env = mkOccEnv_C combine [ (occ, (n, a, Nothing))+ imp_occ_env :: OccEnv (NameEnv (GreName, -- the name or field+ AvailInfo, -- the export item providing it+ Maybe Name)) -- the parent of associated types+ imp_occ_env = mkOccEnv_C (plusNameEnv_C combine)+ [ (occName c, mkNameEnv [(greNameMangledName c, (c, a, Nothing))]) | a <- all_avails- , (n, occ) <- availNamesWithOccs a]- where- -- See Note [Dealing with imports]- -- 'combine' is only called for associated data types which appear- -- twice in the all_avails. In the example, we combine- -- T(T,T1,T2,T3) and C(C,T) to give (T, T(T,T1,T2,T3), Just C)- -- NB: the AvailTC can have fields as well as data constructors (#12127)- combine (name1, a1@(AvailTC p1 _ _), mp1)- (name2, a2@(AvailTC p2 _ _), mp2)- = ASSERT2( name1 == name2 && isNothing mp1 && isNothing mp2- , ppr name1 <+> ppr name2 <+> ppr mp1 <+> ppr mp2 )- if p1 == name1 then (name1, a1, Just p2)- else (name1, a2, Just p1)- combine x y = pprPanic "filterImports/combine" (ppr x $$ ppr y)+ , c <- availGreNames a]+ -- See Note [Dealing with imports]+ -- 'combine' may be called for associated data types which appear+ -- twice in the all_avails. In the example, we combine+ -- T(T,T1,T2,T3) and C(C,T) to give (T, T(T,T1,T2,T3), Just C)+ -- NB: the AvailTC can have fields as well as data constructors (#12127)+ combine :: (GreName, AvailInfo, Maybe Name)+ -> (GreName, AvailInfo, Maybe Name)+ -> (GreName, AvailInfo, Maybe Name)+ combine (NormalGreName name1, a1@(AvailTC p1 _), mb1)+ (NormalGreName name2, a2@(AvailTC p2 _), mb2)+ = ASSERT2( name1 == name2 && isNothing mb1 && isNothing mb2+ , ppr name1 <+> ppr name2 <+> ppr mb1 <+> ppr mb2 )+ if p1 == name1 then (NormalGreName name1, a1, Just p2)+ else (NormalGreName name1, a2, Just p1)+ -- 'combine' may also be called for pattern synonyms which appear both+ -- unassociated and associated (see Note [Importing PatternSynonyms]).+ combine (c1, a1, mb1) (c2, a2, mb2)+ = ASSERT2( c1 == c2 && isNothing mb1 && isNothing mb2+ && (isAvailTC a1 || isAvailTC a2)+ , ppr c1 <+> ppr c2 <+> ppr a1 <+> ppr a2 <+> ppr mb1 <+> ppr mb2 )+ if isAvailTC a1 then (c1, a1, Nothing)+ else (c1, a2, Nothing) + isAvailTC AvailTC{} = True+ isAvailTC _ = False+ lookup_name :: IE GhcPs -> RdrName -> IELookupM (Name, AvailInfo, Maybe Name) lookup_name ie rdr | isQual rdr = failLookupWith (QualImportError rdr)- | Just succ <- mb_success = return succ+ | Just succ <- mb_success = case nameEnvElts succ of+ -- See Note [Importing DuplicateRecordFields]+ [(c,a,x)] -> return (greNameMangledName c, a, x)+ xs -> failLookupWith (AmbiguousImport rdr (map sndOf3 xs)) | otherwise = failLookupWith (BadImport ie) where mb_success = lookupOccEnv imp_occ_env (rdrNameOcc rdr)@@ -1011,6 +1141,7 @@ BadImport ie -> badImportItemErr iface decl_spec ie all_avails IllegalImport -> illegalImportItemErr QualImportError rdr -> qualImportItemErr rdr+ AmbiguousImport rdr xs -> ambiguousImportItemErr rdr xs -- For each import item, we convert its RdrNames to Names, -- and at the same time construct an AvailInfo corresponding@@ -1037,8 +1168,8 @@ Avail {} -- e.g. f(..) -> [DodgyImport $ ieWrappedName tc] - AvailTC _ subs fs- | null (drop 1 subs) && null fs -- e.g. T(..) where T is a synonym+ AvailTC _ subs+ | null (drop 1 subs) -- e.g. T(..) where T is a synonym -> [DodgyImport $ ieWrappedName tc] | not (is_qual decl_spec) -- e.g. import M( T(..) )@@ -1049,12 +1180,12 @@ renamed_ie = IEThingAll noExtField (L l (replaceWrappedName tc name)) sub_avails = case avail of- Avail {} -> []- AvailTC name2 subs fs -> [(renamed_ie, AvailTC name2 (subs \\ [name]) fs)]+ Avail {} -> []+ AvailTC name2 subs -> [(renamed_ie, AvailTC name2 (subs \\ [NormalGreName name]))] case mb_parent of Nothing -> return ([(renamed_ie, avail)], warns) -- non-associated ty/cls- Just parent -> return ((renamed_ie, AvailTC parent [name] []) : sub_avails, warns)+ Just parent -> return ((renamed_ie, AvailTC parent [NormalGreName name]) : sub_avails, warns) -- associated type IEThingAbs _ (L l tc')@@ -1073,25 +1204,16 @@ return ([mkIEThingAbs tc' l nameAvail] , []) - IEThingWith xt ltc@(L l rdr_tc) wc rdr_ns rdr_fs ->- ASSERT2(null rdr_fs, ppr rdr_fs) do+ IEThingWith xt ltc@(L l rdr_tc) wc rdr_ns -> do (name, avail, mb_parent) <- lookup_name (IEThingAbs noExtField ltc) (ieWrappedName rdr_tc) - let (ns,subflds) = case avail of- AvailTC _ ns' subflds' -> (ns',subflds')- Avail _ -> panic "filterImports"- -- Look up the children in the sub-names of the parent- let subnames = case ns of -- The tc is first in ns,- [] -> [] -- if it is there at all- -- See the AvailTC Invariant in- -- GHC.Types.Avail- (n1:ns1) | n1 == name -> ns1- | otherwise -> ns- case lookupChildren (map Left subnames ++ map Right subflds) rdr_ns of+ -- See Note [Importing DuplicateRecordFields]+ let subnames = availSubordinateGreNames avail+ case lookupChildren subnames rdr_ns of - Failed rdrs -> failLookupWith (BadImport (IEThingWith xt ltc wc rdrs []))+ Failed rdrs -> failLookupWith (BadImport (IEThingWith xt ltc wc rdrs)) -- We are trying to import T( a,b,c,d ), and failed -- to find 'b' and 'd'. So we make up an import item -- to report as failing, namely T( b, d ).@@ -1101,21 +1223,18 @@ case mb_parent of -- non-associated ty/cls Nothing- -> return ([(IEThingWith noExtField (L l name') wc childnames'- childflds,- AvailTC name (name:map unLoc childnames) (map unLoc childflds))],+ -> return ([(IEThingWith childflds (L l name') wc childnames',+ availTC name (name:map unLoc childnames) (map unLoc childflds))], []) where name' = replaceWrappedName rdr_tc name childnames' = map to_ie_post_rn childnames -- childnames' = postrn_ies childnames -- associated ty Just parent- -> return ([(IEThingWith noExtField (L l name') wc childnames'- childflds,- AvailTC name (map unLoc childnames) (map unLoc childflds)),- (IEThingWith noExtField (L l name') wc childnames'- childflds,- AvailTC parent [name] [])],+ -> return ([(IEThingWith childflds (L l name') wc childnames',+ availTC name (map unLoc childnames) (map unLoc childflds)),+ (IEThingWith childflds (L l name') wc childnames',+ availTC parent [name] [])], []) where name' = replaceWrappedName rdr_tc name childnames' = map to_ie_post_rn childnames@@ -1129,7 +1248,7 @@ = (IEThingAbs noExtField (L l (replaceWrappedName tc n)), trimAvail av n) mkIEThingAbs tc l (n, _, Just parent) = (IEThingAbs noExtField (L l (replaceWrappedName tc n))- , AvailTC parent [n] [])+ , availTC parent [n] []) handle_bad_import m = catchIELookup m $ \err -> case err of BadImport ie | want_hiding -> return ([], [BadImportW ie])@@ -1147,6 +1266,7 @@ = QualImportError RdrName | BadImport (IE GhcPs) | IllegalImport+ | AmbiguousImport RdrName [AvailInfo] -- e.g. a duplicated field name as a top-level import failLookupWith :: IELookupError -> IELookupM a failLookupWith err = Failed err@@ -1201,14 +1321,13 @@ mkChildEnv gres = foldr add emptyNameEnv gres where add gre env = case gre_par gre of- FldParent p _ -> extendNameEnv_Acc (:) Utils.singleton env p gre ParentIs p -> extendNameEnv_Acc (:) Utils.singleton env p gre NoParent -> env findChildren :: NameEnv [a] -> Name -> [a] findChildren env n = lookupNameEnv env n `orElse` [] -lookupChildren :: [Either Name FieldLabel] -> [LIEWrappedName RdrName]+lookupChildren :: [GreName] -> [LIEWrappedName RdrName] -> MaybeErr [LIEWrappedName RdrName] -- The ones for which the lookup failed ([Located Name], [Located FieldLabel]) -- (lookupChildren all_kids rdr_items) maps each rdr_item to its@@ -1233,13 +1352,13 @@ doOne item@(L l r) = case (lookupFsEnv kid_env . occNameFS . rdrNameOcc . ieWrappedName) r of- Just [Left n] -> Succeeded (Left (L l n))- Just rs | all isRight rs -> Succeeded (Right (map (L l) (rights rs)))- _ -> Failed item+ Just [NormalGreName n] -> Succeeded (Left (L l n))+ Just rs | Just fs <- traverse greNameFieldLabel rs -> Succeeded (Right (map (L l) fs))+ _ -> Failed item -- See Note [Children for duplicate record fields] kid_env = extendFsEnvList_C (++) emptyFsEnv- [(either (occNameFS . nameOccName) flLabel x, [x]) | x <- all_kids]+ [(occNameFS (occName x), [x]) | x <- all_kids] @@ -1274,11 +1393,13 @@ -- This is done in mkExports too; duplicated work gre_is_used :: NameSet -> GlobalRdrElt -> Bool- gre_is_used used_names (GRE {gre_name = name})+ gre_is_used used_names gre0 = name `elemNameSet` used_names- || any (\ gre -> gre_name gre `elemNameSet` used_names) (findChildren kids_env name)+ || any (\ gre -> greMangledName gre `elemNameSet` used_names) (findChildren kids_env name) -- A use of C implies a use of T, -- if C was brought into scope by T(..) or T(C)+ where+ name = greMangledName gre0 -- Filter out the ones that are -- (a) defined in this module, and@@ -1295,7 +1416,7 @@ in filter is_unused_local defined_but_not_used is_unused_local :: GlobalRdrElt -> Bool- is_unused_local gre = isLocalGRE gre && isExternalName (gre_name gre)+ is_unused_local gre = isLocalGRE gre && isExternalName (greMangledName gre) {- ********************************************************************* * *@@ -1422,7 +1543,7 @@ -- srcSpanEnd: see Note [The ImportMap] `orElse` [] - used_names = mkNameSet (map gre_name used_gres)+ used_names = mkNameSet (map greMangledName used_gres) used_parents = mkNameSet (mapMaybe greParent_maybe used_gres) unused_imps -- Not trivial; see eg #7454@@ -1435,7 +1556,7 @@ add_unused (IEVar _ n) acc = add_unused_name (lieWrappedName n) acc add_unused (IEThingAbs _ n) acc = add_unused_name (lieWrappedName n) acc add_unused (IEThingAll _ n) acc = add_unused_all (lieWrappedName n) acc- add_unused (IEThingWith _ p wc ns fs) acc =+ add_unused (IEThingWith fs p wc ns) acc = add_wc_all (add_unused_with pn xs acc) where pn = lieWrappedName p xs = map lieWrappedName ns ++ map (flSelector . unLoc) fs@@ -1501,7 +1622,7 @@ best_imp_spec = bestImport imp_specs add _ gres = gre : gres -warnUnusedImport :: WarningFlag -> NameEnv (FieldLabelString, Name)+warnUnusedImport :: WarningFlag -> NameEnv (FieldLabelString, Parent) -> ImportDeclUsage -> RnM () warnUnusedImport flag fld_env (L loc decl, used, unused) @@ -1553,8 +1674,9 @@ -- to improve the consistent for ambiguous/unambiguous identifiers. -- See trac#14881. ppr_possible_field n = case lookupNameEnv fld_env n of- Just (fld, p) -> pprNameUnqualified p <> parens (ppr fld)- Nothing -> pprNameUnqualified n+ Just (fld, ParentIs p) -> pprNameUnqualified p <> parens (ppr fld)+ Just (fld, NoParent) -> ppr fld+ Nothing -> pprNameUnqualified n -- Print unused names in a deterministic (lexicographic) order sort_unused :: SDoc@@ -1606,35 +1728,30 @@ -- The main trick here is that if we're importing all the constructors -- we want to say "T(..)", but if we're importing only a subset we want -- to say "T(A,B,C)". So we have to find out what the module exports.- to_ie _ (Avail n)- = [IEVar noExtField (to_ie_post_rn $ noLoc n)]- to_ie _ (AvailTC n [m] [])- | n==m = [IEThingAbs noExtField (to_ie_post_rn $ noLoc n)]- to_ie iface (AvailTC n ns fs)- = case [(xs,gs) | AvailTC x xs gs <- mi_exports iface+ to_ie _ (Avail c) -- Note [Overloaded field import]+ = [IEVar noExtField (to_ie_post_rn $ noLoc (greNamePrintableName c))]+ to_ie _ avail@(AvailTC n [_]) -- Exporting the main decl and nothing else+ | availExportsDecl avail = [IEThingAbs noExtField (to_ie_post_rn $ noLoc n)]+ to_ie iface (AvailTC n cs)+ = case [xs | avail@(AvailTC x xs) <- mi_exports iface , x == n- , x `elem` xs -- Note [Partial export]+ , availExportsDecl avail -- Note [Partial export] ] of [xs] | all_used xs -> [IEThingAll noExtField (to_ie_post_rn $ noLoc n)] | otherwise ->- [IEThingWith noExtField (to_ie_post_rn $ noLoc n) NoIEWildcard- (map (to_ie_post_rn . noLoc) (filter (/= n) ns))- (map noLoc fs)]+ [IEThingWith (map noLoc fs) (to_ie_post_rn $ noLoc n) NoIEWildcard+ (map (to_ie_post_rn . noLoc) (filter (/= n) ns))] -- Note [Overloaded field import] _other | all_non_overloaded fs -> map (IEVar noExtField . to_ie_post_rn_var . noLoc) $ ns ++ map flSelector fs | otherwise ->- [IEThingWith noExtField (to_ie_post_rn $ noLoc n) NoIEWildcard- (map (to_ie_post_rn . noLoc) (filter (/= n) ns))- (map noLoc fs)]+ [IEThingWith (map noLoc fs) (to_ie_post_rn $ noLoc n) NoIEWildcard+ (map (to_ie_post_rn . noLoc) (filter (/= n) ns))] where-- fld_lbls = map flLabel fs+ (ns, fs) = partitionGreNames cs - all_used (avail_occs, avail_flds)- = all (`elem` ns) avail_occs- && all (`elem` fld_lbls) (map flLabel avail_flds)+ all_used avail_cs = all (`elem` cs) avail_cs all_non_overloaded = all (not . flIsOverloaded) @@ -1713,7 +1830,7 @@ not import A( C( op ) ) which we would usually generate if C was exported from B. Hence-the (x `elem` xs) test when deciding what to generate.+the availExportsDecl test when deciding what to generate. Note [Overloaded field import]@@ -1733,7 +1850,24 @@ because when DuplicateRecordFields is enabled, field selectors are not in scope without their enclosing datatype. +On the third hand, if we have + {-# LANGUAGE DuplicateRecordFields #-}+ module A where+ pattern MkT { foo } = Just foo++ module B where+ import A+ f = ...foo...++then the minimal import for module B must be+ import A ( foo )+because foo doesn't have a parent. This might actually be ambiguous if A+exports another field called foo, but there is no good answer to return and this+is a very obscure corner, so it seems to be the best we can do. See+DRFPatSynExport for a test of this.++ ************************************************************************ * * \subsection{Errors}@@ -1746,6 +1880,14 @@ = hang (text "Illegal qualified name in import item:") 2 (ppr rdr) +ambiguousImportItemErr :: RdrName -> [AvailInfo] -> SDoc+ambiguousImportItemErr rdr avails+ = hang (text "Ambiguous name" <+> quotes (ppr rdr) <+> text "in import item. It could refer to:")+ 2 (vcat (map ppr_avail avails))+ where+ ppr_avail (AvailTC parent _) = ppr parent <> parens (ppr rdr)+ ppr_avail (Avail name) = ppr name+ pprImpDeclSpec :: ModIface -> ImpDeclSpec -> SDoc pprImpDeclSpec iface decl_spec = quotes (ppr (is_mod decl_spec)) <+> case mi_boot iface of@@ -1787,13 +1929,12 @@ Just con -> badImportItemErrDataCon (availOccName con) iface decl_spec ie Nothing -> badImportItemErrStd iface decl_spec ie where- checkIfDataCon (AvailTC _ ns _) =- case find (\n -> importedFS == nameOccNameFS n) ns of- Just n -> isDataConName n+ checkIfDataCon (AvailTC _ ns) =+ case find (\n -> importedFS == occNameFS (occName n)) ns of+ Just n -> isDataConName (greNameMangledName n) Nothing -> False checkIfDataCon _ = False- availOccName = nameOccName . availName- nameOccNameFS = occNameFS . nameOccName+ availOccName = occName . availGreName importedFS = occNameFS . rdrNameOcc $ ieName ie illegalImportItemErr :: SDoc@@ -1834,7 +1975,7 @@ where sorted_names = sortBy (SrcLoc.leftmost_smallest `on` nameSrcSpan)- (map gre_name gres)+ (map greMangledName gres)
compiler/GHC/Rename/Pat.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}@@ -32,7 +33,7 @@ rnHsRecUpdFields, -- CpsRn monad- CpsRn, liftCps,+ CpsRn, liftCps, liftCpsWithCont, -- Literals rnLit, rnOverLit,@@ -77,8 +78,9 @@ import GHC.Core.DataCon import qualified GHC.LanguageExtensions as LangExt -import Control.Monad ( when, ap, guard )+import Control.Monad ( when, ap, guard, forM, unless ) import qualified Data.List.NonEmpty as NE+import Data.Maybe import Data.Ratio {-@@ -133,6 +135,9 @@ ; (r,fvs2) <- k v ; return (r, fvs1 `plusFV` fvs2) }) +liftCpsWithCont :: (forall r. (b -> RnM (r, FreeVars)) -> RnM (r, FreeVars)) -> CpsRn b+liftCpsWithCont = CpsRn+ wrapSrcSpanCps :: (a -> CpsRn b) -> Located a -> CpsRn (Located b) -- Set the location, and also wrap it around the value returned wrapSrcSpanCps fn (L loc a)@@ -424,7 +429,7 @@ ; return (SigPat x pat' sig' ) } where rnHsPatSigTypeAndThen :: HsPatSigType GhcPs -> CpsRn (HsPatSigType GhcRn)- rnHsPatSigTypeAndThen sig = CpsRn (rnHsPatSigType AlwaysBind PatCtx sig)+ rnHsPatSigTypeAndThen sig = liftCpsWithCont (rnHsPatSigType AlwaysBind PatCtx sig) rnPatAndThen mk (LitPat x lit) | HsString src s <- lit@@ -522,15 +527,31 @@ -> HsConPatDetails GhcPs -> CpsRn (Pat GhcRn) -rnConPatAndThen mk con (PrefixCon pats)+rnConPatAndThen mk con (PrefixCon tyargs pats) = do { con' <- lookupConCps con+ ; liftCps check_lang_exts+ ; tyargs' <- forM tyargs $ \t ->+ liftCpsWithCont $ rnHsPatSigTypeBindingVars HsTypeCtx t ; pats' <- rnLPatsAndThen mk pats ; return $ ConPat { pat_con_ext = noExtField , pat_con = con'- , pat_args = PrefixCon pats'+ , pat_args = PrefixCon tyargs' pats' } }+ where+ check_lang_exts :: RnM ()+ check_lang_exts = do+ scoped_tyvars <- xoptM LangExt.ScopedTypeVariables+ type_app <- xoptM LangExt.TypeApplications+ unless (scoped_tyvars && type_app) $+ case listToMaybe tyargs of+ Nothing -> pure ()+ Just tyarg -> addErr $+ hang (text "Illegal visible type application in a pattern:"+ <+> quotes (char '@' <> ppr tyarg))+ 2 (text "Both ScopedTypeVariables and TypeApplications are"+ <+> text "required to use this feature") rnConPatAndThen mk con (InfixCon pat1 pat2) = do { con' <- lookupConCps con
compiler/GHC/Rename/Splice.hs view
@@ -433,7 +433,7 @@ traceRn "rnSpliceExpr: typed expression splice" empty ; lcl_rdr <- getLocalRdrEnv ; gbl_rdr <- getGlobalRdrEnv- ; let gbl_names = mkNameSet [gre_name gre | gre <- globalRdrEnvElts gbl_rdr+ ; let gbl_names = mkNameSet [greMangledName gre | gre <- globalRdrEnvElts gbl_rdr , isLocalGRE gre] lcl_names = mkNameSet (localRdrEnvElts lcl_rdr)
compiler/GHC/Rename/Unbound.hs view
@@ -180,8 +180,7 @@ | tried_is_qual = [ (rdr_qual, (rdr_qual, how)) | gre <- globalRdrEnvElts global_env , isGreOk where_look gre- , let name = gre_name gre- occ = nameOccName name+ , let occ = greOccName gre , correct_name_space occ , (mod, how) <- qualsInScope gre , let rdr_qual = mkRdrQual mod occ ]@@ -189,8 +188,7 @@ | otherwise = [ (rdr_unqual, pair) | gre <- globalRdrEnvElts global_env , isGreOk where_look gre- , let name = gre_name gre- occ = nameOccName name+ , let occ = greOccName gre rdr_unqual = mkRdrUnqual occ , correct_name_space occ , pair <- case (unquals_in_scope gre, quals_only gre) of@@ -210,8 +208,8 @@ -------------------- unquals_in_scope :: GlobalRdrElt -> [HowInScope]- unquals_in_scope (GRE { gre_name = n, gre_lcl = lcl, gre_imp = is })- | lcl = [ Left (nameSrcSpan n) ]+ unquals_in_scope (gre@GRE { gre_lcl = lcl, gre_imp = is })+ | lcl = [ Left (greDefinitionSrcSpan gre) ] | otherwise = [ Right ispec | i <- is, let ispec = is_decl i , not (is_qual ispec) ]@@ -220,8 +218,8 @@ -------------------- quals_only :: GlobalRdrElt -> [(RdrName, HowInScope)] -- Ones for which *only* the qualified version is in scope- quals_only (GRE { gre_name = n, gre_imp = is })- = [ (mkRdrQual (is_as ispec) (nameOccName n), Right ispec)+ quals_only (gre@GRE { gre_imp = is })+ = [ (mkRdrQual (is_as ispec) (greOccName gre), Right ispec) | i <- is, let ispec = is_decl i, is_qual ispec ] -- | Generate helpful suggestions if a qualified name Mod.foo is not in scope.@@ -366,10 +364,10 @@ qualsInScope :: GlobalRdrElt -> [(ModuleName, HowInScope)] -- Ones for which the qualified version is in scope-qualsInScope GRE { gre_name = n, gre_lcl = lcl, gre_imp = is }- | lcl = case nameModule_maybe n of+qualsInScope gre@GRE { gre_lcl = lcl, gre_imp = is }+ | lcl = case greDefinitionModule gre of Nothing -> []- Just m -> [(moduleName m, Left (nameSrcSpan n))]+ Just m -> [(moduleName m, Left (greDefinitionSrcSpan gre))] | otherwise = [ (is_as ispec, Right ispec) | i <- is, let ispec = is_decl i ]
compiler/GHC/Rename/Utils.hs view
@@ -423,30 +423,26 @@ warnUnusedGREs :: [GlobalRdrElt] -> RnM () warnUnusedGREs gres = mapM_ warnUnusedGRE gres +-- NB the Names must not be the names of record fields! warnUnused :: WarningFlag -> [Name] -> RnM ()-warnUnused flag names = do- fld_env <- mkFieldEnv <$> getGlobalRdrEnv- mapM_ (warnUnused1 flag fld_env) names+warnUnused flag names =+ mapM_ (warnUnused1 flag . NormalGreName) names -warnUnused1 :: WarningFlag -> NameEnv (FieldLabelString, Name) -> Name -> RnM ()-warnUnused1 flag fld_env name- = when (reportable name occ) $+warnUnused1 :: WarningFlag -> GreName -> RnM ()+warnUnused1 flag child+ = when (reportable child) $ addUnusedWarning flag- occ (nameSrcSpan name)+ (occName child) (greNameSrcSpan child) (text $ "Defined but not used" ++ opt_str) where- occ = case lookupNameEnv fld_env name of- Just (fl, _) -> mkVarOccFS fl- Nothing -> nameOccName name opt_str = case flag of Opt_WarnUnusedTypePatterns -> " on the right hand side" _ -> "" warnUnusedGRE :: GlobalRdrElt -> RnM ()-warnUnusedGRE gre@(GRE { gre_name = name, gre_lcl = lcl, gre_imp = is })- | lcl = do fld_env <- mkFieldEnv <$> getGlobalRdrEnv- warnUnused1 Opt_WarnUnusedTopBinds fld_env name- | otherwise = when (reportable name occ) (mapM_ warn is)+warnUnusedGRE gre@(GRE { gre_lcl = lcl, gre_imp = is })+ | lcl = warnUnused1 Opt_WarnUnusedTopBinds (gre_name gre)+ | otherwise = when (reportable (gre_name gre)) (mapM_ warn is) where occ = greOccName gre warn spec = addUnusedWarning Opt_WarnUnusedTopBinds occ span msg@@ -457,22 +453,23 @@ -- | Make a map from selector names to field labels and parent tycon -- names, to be used when reporting unused record fields.-mkFieldEnv :: GlobalRdrEnv -> NameEnv (FieldLabelString, Name)-mkFieldEnv rdr_env = mkNameEnv [ (gre_name gre, (lbl, par_is (gre_par gre)))+mkFieldEnv :: GlobalRdrEnv -> NameEnv (FieldLabelString, Parent)+mkFieldEnv rdr_env = mkNameEnv [ (greMangledName gre, (flLabel fl, gre_par gre)) | gres <- occEnvElts rdr_env , gre <- gres- , Just lbl <- [greLabel gre]+ , Just fl <- [greFieldLabel gre] ] -- | Should we report the fact that this 'Name' is unused? The -- 'OccName' may differ from 'nameOccName' due to -- DuplicateRecordFields.-reportable :: Name -> OccName -> Bool-reportable name occ- | isWiredInName name = False -- Don't report unused wired-in names+reportable :: GreName -> Bool+reportable child+ | NormalGreName name <- child+ , isWiredInName name = False -- Don't report unused wired-in names -- Otherwise we get a zillion warnings -- from Data.Tuple- | otherwise = not (startsWithUnderscore occ)+ | otherwise = not (startsWithUnderscore (occName child)) addUnusedWarning :: WarningFlag -> OccName -> SrcSpan -> SDoc -> RnM () addUnusedWarning flag occ span msg@@ -508,7 +505,7 @@ (np1:nps) = gres msg1 = text "either" <+> ppr_gre np1 msgs = [text " or" <+> ppr_gre np | np <- nps]- ppr_gre gre = sep [ pp_gre_name gre <> comma+ ppr_gre gre = sep [ pp_greMangledName gre <> comma , pprNameProvenance gre] -- When printing the name, take care to qualify it in the same@@ -519,14 +516,14 @@ -- imported from ‘Prelude’ at T15487.hs:1:8-13 -- or ... -- See #15487- pp_gre_name gre@(GRE { gre_name = name, gre_par = parent- , gre_lcl = lcl, gre_imp = iss })- | FldParent { par_lbl = Just lbl } <- parent- = text "the field" <+> quotes (ppr lbl)- | otherwise- = quotes (pp_qual <> dot <> ppr (nameOccName name))+ pp_greMangledName gre@(GRE { gre_name = child+ , gre_lcl = lcl, gre_imp = iss }) =+ case child of+ FieldGreName fl -> text "the field" <+> quotes (ppr fl)+ NormalGreName name -> quotes (pp_qual name <> dot <> ppr (nameOccName name)) where- pp_qual | lcl+ pp_qual name+ | lcl = ppr (nameModule name) | imp : _ <- iss -- This 'imp' is the one that -- pprNameProvenance chooses@@ -619,6 +616,7 @@ | ExprWithTySigCtx | TypBrCtx | HsTypeCtx+ | HsTypePatCtx | GHCiCtx | SpliceTypeCtx (LHsType GhcPs) | ClassInstanceCtx@@ -647,6 +645,7 @@ pprHsDocContext ExprWithTySigCtx = text "an expression type signature" pprHsDocContext TypBrCtx = text "a Template-Haskell quoted type" pprHsDocContext HsTypeCtx = text "a type argument"+pprHsDocContext HsTypePatCtx = text "a type argument in a pattern" pprHsDocContext GHCiCtx = text "GHCi input" pprHsDocContext (SpliceTypeCtx hs_ty) = text "the spliced type" <+> quotes (ppr hs_ty) pprHsDocContext ClassInstanceCtx = text "GHC.Tc.Gen.Splice.reifyInstances"
compiler/GHC/Runtime/Eval.hs view
@@ -17,7 +17,6 @@ Resume(..), History(..), execStmt, execStmt', ExecOptions(..), execOptions, ExecResult(..), resumeExec, runDecls, runDeclsWithLocation, runParsedDecls,- isStmt, hasImport, isImport, isDecl, parseImportDecl, SingleStep(..), abandon, abandonAll, getResumeContext,@@ -26,7 +25,6 @@ getHistoryModule, back, forward, setContext, getContext,- availsToGlobalRdrEnv, getNamesInScope, getRdrNamesInScope, moduleIsInterpreted,@@ -96,17 +94,12 @@ import GHC.Utils.Outputable import GHC.Utils.Misc -import qualified GHC.Parser.Lexer as Lexer (P (..), ParseResult(..), unP, initParserState)-import GHC.Parser.Lexer (ParserOpts)-import qualified GHC.Parser as Parser (parseStmt, parseModule, parseDeclaration, parseImport)- import GHC.Types.RepType import GHC.Types.Fixity.Env import GHC.Types.Var import GHC.Types.Id as Id import GHC.Types.Name hiding ( varName ) import GHC.Types.Name.Set-import GHC.Types.Avail import GHC.Types.Name.Reader import GHC.Types.Var.Env import GHC.Types.SrcLoc@@ -115,6 +108,7 @@ import GHC.Types.TyThing import GHC.Unit+import GHC.Unit.Module.Graph import GHC.Unit.Module.ModIface import GHC.Unit.Module.ModSummary import GHC.Unit.Home.ModInfo@@ -126,7 +120,6 @@ import Data.List (find,intercalate) import Data.Map (Map) import qualified Data.Map as Map-import GHC.Data.StringBuffer (stringToStringBuffer) import Control.Monad import Control.Monad.Catch as MC import Data.Array@@ -796,17 +789,6 @@ Left err -> Left (mod, err) Right env -> Right env -availsToGlobalRdrEnv :: ModuleName -> [AvailInfo] -> GlobalRdrEnv-availsToGlobalRdrEnv mod_name avails- = mkGlobalRdrEnv (gresFromAvails (Just imp_spec) avails)- where- -- We're building a GlobalRdrEnv as if the user imported- -- all the specified modules into the global interactive module- imp_spec = ImpSpec { is_decl = decl, is_item = ImpAll}- decl = ImpDeclSpec { is_mod = mod_name, is_as = mod_name,- is_qual = False,- is_dloc = srcLocSpan interactiveSrcLoc }- mkTopLevEnv :: HomePackageTable -> ModuleName -> Either String GlobalRdrEnv mkTopLevEnv hpt modl = case lookupHpt hpt modl of@@ -871,7 +853,7 @@ -- | Returns all names in scope in the current interactive context getNamesInScope :: GhcMonad m => m [Name] getNamesInScope = withSession $ \hsc_env ->- return (map gre_name (globalRdrEnvElts (ic_rn_gbl_env (hsc_IC hsc_env))))+ return (map greMangledName (globalRdrEnvElts (ic_rn_gbl_env (hsc_IC hsc_env)))) -- | Returns all 'RdrName's in scope in the current interactive -- context, excluding any that are internally-generated.@@ -892,46 +874,7 @@ do { lrdr_name <- hscParseIdentifier hsc_env str ; hscTcRnLookupRdrName hsc_env lrdr_name } --- | Returns @True@ if passed string is a statement.-isStmt :: ParserOpts -> String -> Bool-isStmt pflags stmt =- case parseThing Parser.parseStmt pflags stmt of- Lexer.POk _ _ -> True- Lexer.PFailed _ -> False --- | Returns @True@ if passed string has an import declaration.-hasImport :: ParserOpts -> String -> Bool-hasImport pflags stmt =- case parseThing Parser.parseModule pflags stmt of- Lexer.POk _ thing -> hasImports thing- Lexer.PFailed _ -> False- where- hasImports = not . null . hsmodImports . unLoc---- | Returns @True@ if passed string is an import declaration.-isImport :: ParserOpts -> String -> Bool-isImport pflags stmt =- case parseThing Parser.parseImport pflags stmt of- Lexer.POk _ _ -> True- Lexer.PFailed _ -> False---- | Returns @True@ if passed string is a declaration but __/not a splice/__.-isDecl :: ParserOpts -> String -> Bool-isDecl pflags stmt =- case parseThing Parser.parseDeclaration pflags stmt of- Lexer.POk _ thing ->- case unLoc thing of- SpliceD _ _ -> False- _ -> True- Lexer.PFailed _ -> False--parseThing :: Lexer.P thing -> ParserOpts -> String -> Lexer.ParseResult thing-parseThing parser opts stmt = do- let buf = stringToStringBuffer stmt- loc = mkRealSrcLoc (fsLit "<interactive>") 1 1-- Lexer.unP parser (Lexer.initParserState opts buf loc)- getDocs :: GhcMonad m => Name -> m (Either GetDocsFailure (Maybe HsDocString, Map Int HsDocString))@@ -1272,7 +1215,8 @@ withSession $ \hsc_env -> do interpreted <- moduleIsBootOrNotObjectLinkable mod_summary let dflags = hsc_dflags hsc_env- return (showSDoc dflags $ showModMsg dflags interpreted mod_summary)+ -- extendModSummaryNoDeps because the message doesn't look at the deps+ return (showSDoc dflags $ showModMsg dflags interpreted (ModuleNode (extendModSummaryNoDeps mod_summary))) moduleIsBootOrNotObjectLinkable :: GhcMonad m => ModSummary -> m Bool moduleIsBootOrNotObjectLinkable mod_summary = withSession $ \hsc_env ->
compiler/GHC/Runtime/Heap/Inspect.hs view
@@ -577,7 +577,7 @@ ~~~~~~~~~~~~~~~~~~~~~~ In the GHCi debugger we use unification variables whose MetaInfo is RuntimeUnkTv. The special property of a RuntimeUnkTv is that it can-unify with a polytype (see GHC.Tc.Utils.Unify.metaTyVarUpdateOK).+unify with a polytype (see GHC.Tc.Utils.Unify.checkTypeEq). If we don't do this `:print <term>` will fail if the type of <term> has nested `forall`s or `=>`s.
compiler/GHC/Runtime/Loader.hs view
@@ -32,7 +32,7 @@ import GHC.Runtime.Interpreter.Types import GHC.Tc.Utils.Monad ( initTcInteractive, initIfaceTcRn )-import GHC.Iface.Load ( loadPluginInterface )+import GHC.Iface.Load ( loadPluginInterface, cannotFindModule ) import GHC.Rename.Names ( gresFromAvails ) import GHC.Builtin.Names ( pluginTyConName, frontendPluginTyConName ) @@ -48,9 +48,9 @@ import GHC.Types.Name.Occurrence ( OccName, mkVarOcc ) import GHC.Types.Name.Reader ( RdrName, ImportSpec(..), ImpDeclSpec(..) , ImpItemSpec(..), mkGlobalRdrEnv, lookupGRE_RdrName- , gre_name, mkRdrQual )+ , greMangledName, mkRdrQual ) -import GHC.Unit.Finder ( findPluginModule, cannotFindModule, FindResult(..) )+import GHC.Unit.Finder ( findPluginModule, FindResult(..) ) import GHC.Unit.Module ( Module, ModuleName ) import GHC.Unit.Module.ModIface @@ -268,12 +268,12 @@ imp_spec = ImpSpec decl_spec ImpAll env = mkGlobalRdrEnv (gresFromAvails (Just imp_spec) (mi_exports iface)) case lookupGRE_RdrName rdr_name env of- [gre] -> return (Just (gre_name gre, iface))+ [gre] -> return (Just (greMangledName gre, iface)) [] -> return Nothing _ -> panic "lookupRdrNameInModule" Nothing -> throwCmdLineErrorS dflags $ hsep [text "Could not determine the exports of the module", ppr mod_name]- err -> throwCmdLineErrorS dflags $ cannotFindModule dflags mod_name err+ err -> throwCmdLineErrorS dflags $ cannotFindModule hsc_env mod_name err where dflags = hsc_dflags hsc_env doc = text "contains a name used in an invocation of lookupRdrNameInModule"
compiler/GHC/Stg/CSE.hs view
@@ -102,7 +102,8 @@ import GHC.Core (AltCon(..)) import Data.List (mapAccumL) import Data.Maybe (fromMaybe)-import GHC.Core.Map+import GHC.Core.Map.Expr+import GHC.Data.TrieMap import GHC.Types.Name.Env import Control.Monad( (>=>) ) @@ -129,6 +130,8 @@ foldTM k m = foldTM k (sam_var m) . foldTM k (sam_lit m) mapTM f (SAM {sam_var = varm, sam_lit = litm}) = SAM { sam_var = mapTM f varm, sam_lit = mapTM f litm }+ filterTM f (SAM {sam_var = varm, sam_lit = litm}) =+ SAM { sam_var = filterTM f varm, sam_lit = filterTM f litm } newtype ConAppMap a = CAM { un_cam :: DNameEnv (ListMap StgArgMap a) } @@ -140,6 +143,7 @@ m { un_cam = un_cam m |> xtDNamed dataCon |>> alterTM args f } foldTM k = un_cam >.> foldTM (foldTM k) mapTM f = un_cam >.> mapTM (mapTM f) >.> CAM+ filterTM f = un_cam >.> mapTM (filterTM f) >.> CAM ----------------- -- The CSE Env --
compiler/GHC/Tc/Deriv/Generate.hs view
@@ -1819,6 +1819,94 @@ Then the same situation will arise again. But at least it won't arise for the common case of methods with ordinary, prenex-quantified types. +-----+-- Wrinkle: Use HsOuterExplicit+-----++One minor complication with the plan above is that we need to ensure that the+type variables from a method's instance signature properly scope over the body+of the method. For example, recall:++ instance (C m, forall p q. Coercible p q => Coercible (m p) (m q)) =>+ C (T m) where+ join :: forall a. T m (T m a) -> T m a+ join = coerce @( m (m a) -> m a)+ @(T m (T m a) -> T m a)+ join++In the example above, it is imperative that the `a` in the instance signature+for `join` scope over the body of `join` by way of ScopedTypeVariables.+This might sound obvious, but note that in gen_Newtype_binds, which is+responsible for generating the code above, the type in `join`'s instance+signature is given as a Core type, whereas gen_Newtype_binds will eventually+produce HsBinds (i.e., source Haskell) that is renamed and typechecked. We+must ensure that `a` is in scope over the body of `join` during renaming+or else the generated code will be rejected.++In short, we need to convert the instance signature from a Core type to an+HsType (i.e., a source Haskell type). Two possible options are:++1. Convert the Core type entirely to an HsType (i.e., a source Haskell type).+2. Embed the entire Core type using HsCoreTy.++Neither option is quite satisfactory:++1. Converting a Core type to an HsType in full generality is surprisingly+ complicated. Previous versions of GHCs did this, but it was the source of+ numerous bugs (see #14579 and #16518, for instance).+2. While HsCoreTy is much less complicated that option (1), it's not quite+ what we want. In order for `a` to be in scope over the body of `join` during+ renaming, the `forall` must be contained in an HsOuterExplicit.+ (See Note [Lexically scoped type variables] in GHC.Hs.Type.) HsCoreTy+ bypasses HsOuterExplicit, so this won't work either.++As a compromise, we adopt a combination of the two options above:++* Split apart the top-level ForAllTys in the instance signature's Core type,+* Convert the top-level ForAllTys to an HsOuterExplicit, and+* Embed the remainder of the Core type in an HsCoreTy.++This retains most of the simplicity of option (2) while still ensuring that+the type variables are correctly scoped.++Note that splitting apart top-level ForAllTys will expand any type synonyms+in the Core type itself. This ends up being important to fix a corner case+observed in #18914. Consider this example:++ type T f = forall a. f a++ class C f where+ m :: T f++ newtype N f a = MkN (f a)+ deriving C++What code should `deriving C` generate? It will have roughly the following+shape:++ instance C f => C (N f) where+ m :: T (N f)+ m = coerce @(...) (...) (m @f)++At a minimum, we must instantiate `coerce` with `@(T f)` and `@(T (N f))`, but+with the `forall`s removed in order to make them monotypes. However, the+`forall` is hidden underneath the `T` type synonym, so we must first expand `T`+before we can strip of the `forall`. Expanding `T`, we get+`coerce @(forall a. f a) @(forall a. N f a)`, and after omitting the `forall`s,+we get `coerce @(f a) @(N f a)`.++We can't stop there, however, or else we would end up with this code:++ instance C f => C (N f) where+ m :: T (N f)+ m = coerce @(f a) @(N f a) (m @f)++Notice that the type variable `a` is completely unbound. In order to make sure+that `a` is in scope, we must /also/ expand the `T` in `m :: T (N f)` to get+`m :: forall a. N f a`. Fortunately, we will do just that in the plan outlined+above, since when we split off the top-level ForAllTys in the instance+signature, we must first expand the T type synonym.+ Note [GND and ambiguity] ~~~~~~~~~~~~~~~~~~~~~~~~ We make an effort to make the code generated through GND be robust w.r.t.@@ -1891,14 +1979,31 @@ , -- The derived instance signature, e.g., -- -- op :: forall c. a -> [T x] -> c -> Int+ --+ -- Make sure that `forall c` is in an HsOuterExplicit so that it+ -- scopes over the body of `op`. See "Wrinkle: Use HsOuterExplicit" in+ -- Note [GND and QuantifiedConstraints]. L loc $ ClassOpSig noExtField False [loc_meth_RDR]- $ L loc $ mkHsImplicitSigType $ nlHsCoreTy to_ty+ $ L loc $ mkHsExplicitSigType+ (map mk_hs_tvb to_tvbs)+ (nlHsCoreTy to_rho) ) where Pair from_ty to_ty = mkCoerceClassMethEqn cls inst_tvs inst_tys rhs_ty meth_id- (_, _, from_tau) = tcSplitSigmaTy from_ty- (_, _, to_tau) = tcSplitSigmaTy to_ty+ (_, _, from_tau) = tcSplitSigmaTy from_ty+ (to_tvbs, to_rho) = tcSplitForAllInvisTVBinders to_ty+ (_, to_tau) = tcSplitPhiTy to_rho+ -- The use of tcSplitForAllInvisTVBinders above expands type synonyms,+ -- which is important to ensure correct type variable scoping.+ -- See "Wrinkle: Use HsOuterExplicit" in+ -- Note [GND and QuantifiedConstraints]. + mk_hs_tvb :: VarBndr TyVar flag -> LHsTyVarBndr flag GhcPs+ mk_hs_tvb (Bndr tv flag) = noLoc $ KindedTyVar noExtField+ flag+ (noLoc (getRdrName tv))+ (nlHsCoreTy (tyVarKind tv))+ meth_RDR = getRdrName meth_id loc_meth_RDR = L loc meth_RDR @@ -1950,8 +2055,8 @@ where hs_ty = mkHsWildCardBndrs $ parenthesizeHsType appPrec $ nlHsCoreTy s -nlHsCoreTy :: Type -> LHsType GhcPs-nlHsCoreTy = noLoc . XHsType . NHsCoreTy+nlHsCoreTy :: HsCoreTy -> LHsType GhcPs+nlHsCoreTy = noLoc . XHsType mkCoerceClassMethEqn :: Class -- the class being derived -> [TyVar] -- the tvs in the instance head (this includes@@ -2079,15 +2184,15 @@ genAuxBindSpecSig :: SrcSpan -> AuxBindSpec -> LHsSigWcType GhcPs genAuxBindSpecSig loc spec = case spec of DerivCon2Tag tycon _- -> mk_sig $ L loc $ XHsType $ NHsCoreTy $+ -> mk_sig $ L loc $ XHsType $ mkSpecSigmaTy (tyConTyVars tycon) (tyConStupidTheta tycon) $ mkParentType tycon `mkVisFunTyMany` intPrimTy DerivTag2Con tycon _ -> mk_sig $ L loc $- XHsType $ NHsCoreTy $ mkSpecForAllTys (tyConTyVars tycon) $+ XHsType $ mkSpecForAllTys (tyConTyVars tycon) $ intTy `mkVisFunTyMany` mkParentType tycon DerivMaxTag _ _- -> mk_sig (L loc (XHsType (NHsCoreTy intTy)))+ -> mk_sig (L loc (XHsType intTy)) DerivDataDataType _ _ _ -> mk_sig (nlHsTyVar dataType_RDR) DerivDataConstr _ _ _
compiler/GHC/Tc/Deriv/Utils.hs view
@@ -928,8 +928,8 @@ cond_isProduct :: Condition cond_isProduct _ _ rep_tc- | isProductTyCon rep_tc = IsValid- | otherwise = NotValid why+ | Just _ <- tyConSingleDataCon_maybe rep_tc = IsValid+ | otherwise = NotValid why where why = quotes (pprSourceTyCon rep_tc) <+> text "must have precisely one constructor"
compiler/GHC/Tc/Errors.hs view
@@ -21,7 +21,7 @@ import GHC.Tc.Types.Constraint import GHC.Core.Predicate import GHC.Tc.Utils.TcMType-import GHC.Tc.Utils.Unify( occCheckForErrors, MetaTyVarUpdateResult(..) )+import GHC.Tc.Utils.Unify( occCheckForErrors, CheckTyEqResult(..) ) import GHC.Tc.Utils.Env( tcInitTidyEnv ) import GHC.Tc.Utils.TcType import GHC.Tc.Types.Origin@@ -30,10 +30,9 @@ import GHC.Core.Coercion import GHC.Core.TyCo.Rep import GHC.Core.TyCo.Ppr ( pprTyVars, pprWithExplicitKindsWhen, pprSourceTyCon, pprWithTYPE )-import GHC.Core.Unify ( tcMatchTys )+import GHC.Core.Unify ( tcMatchTys, flattenTys ) import GHC.Unit.Module import GHC.Tc.Instance.Family-import GHC.Core.FamInstEnv ( flattenTys ) import GHC.Tc.Utils.Instantiate import GHC.Core.InstEnv import GHC.Core.TyCon@@ -211,8 +210,6 @@ ; traceTc "reportUnsolved (before zonking and tidying)" (ppr wanted) ; wanted <- zonkWC wanted -- Zonk to reveal all information- -- If we are deferring we are going to need /all/ evidence around,- -- including the evidence produced by unflattening (zonkWC) ; let tidy_env = tidyFreeTyCoVars emptyTidyEnv free_tvs free_tvs = filterOut isCoVar $ tyCoVarsOfWCList wanted@@ -620,7 +617,7 @@ -- also checks to make sure the constraint isn't BlockedCIS -- See TcCanonical Note [Equalities with incompatible kinds], (4) unblocked :: (Ct -> Pred -> Bool) -> Ct -> Pred -> Bool- unblocked _ (CIrredCan { cc_status = BlockedCIS }) _ = False+ unblocked _ (CIrredCan { cc_status = BlockedCIS {}}) _ = False unblocked checker ct pred = checker ct pred -- rigid_nom_eq, rigid_nom_tv_eq,@@ -679,7 +676,7 @@ has_gadt_match [] = False has_gadt_match (implic : implics) | PatSkol {} <- ic_info implic- , not (ic_no_eqs implic)+ , ic_given_eqs implic /= NoGivenEqs , ic_warn_inaccessible implic -- Don't bother doing this if -Winaccessible-code isn't enabled. -- See Note [Avoid -Winaccessible-code when deriving] in GHC.Tc.TyCl.Instance.@@ -889,7 +886,10 @@ -- Unlike maybeReportError, these "hole" errors are -- /not/ suppressed by cec_suppress. We want to see them!-maybeReportHoleError ctxt (Hole { hole_sort = TypeHole }) err+maybeReportHoleError ctxt (Hole { hole_sort = hole_sort }) err+ | case hole_sort of TypeHole -> True+ ConstraintHole -> True+ _ -> False -- When -XPartialTypeSignatures is on, warnings (instead of errors) are -- generated for holes in partial type signatures. -- Unless -fwarn-partial-type-signatures is not on,@@ -901,7 +901,7 @@ HoleWarn -> reportWarning (Reason Opt_WarnPartialTypeSignatures) err HoleDefer -> return () -maybeReportHoleError ctxt hole@(Hole { hole_sort = ExprHole _ }) err+maybeReportHoleError ctxt hole err -- Otherwise this is a typed hole in an expression, -- but not for an out-of-scope variable (because that goes through a -- different function)@@ -953,21 +953,24 @@ err_msg = pprLocErrMsg err err_fs = mkFastString $ showSDoc dflags $ err_msg $$ text "(deferred type error)"+ maybeAddDeferredHoleBinding :: ReportErrCtxt -> ErrMsg -> Hole -> TcM ()-maybeAddDeferredHoleBinding ctxt err (Hole { hole_sort = ExprHole ev_id })+maybeAddDeferredHoleBinding ctxt err (Hole { hole_sort = ExprHole (HER ref ref_ty _) }) -- Only add bindings for holes in expressions -- not for holes in partial type signatures -- cf. addDeferredBinding | deferringAnyBindings ctxt = do { dflags <- getDynFlags- ; let err_tm = mkErrorTerm dflags (idType ev_id) err- -- NB: idType ev_id, not hole_ty. hole_ty might be rewritten.+ ; let err_tm = mkErrorTerm dflags ref_ty err+ -- NB: ref_ty, not hole_ty. hole_ty might be rewritten. -- See Note [Holes] in GHC.Tc.Types.Constraint- ; addTcEvBind (cec_binds ctxt) $ mkWantedEvBind ev_id err_tm }+ ; writeMutVar ref err_tm } | otherwise = return () maybeAddDeferredHoleBinding _ _ (Hole { hole_sort = TypeHole }) = return ()+maybeAddDeferredHoleBinding _ _ (Hole { hole_sort = ConstraintHole })+ = return () tryReporters :: ReportErrCtxt -> [ReporterSpec] -> [Ct] -> TcM (ReportErrCtxt, [Ct]) -- Use the first reporter in the list whose predicate says True@@ -1216,6 +1219,9 @@ TypeHole -> vcat [ hang (text "Found type wildcard" <+> quotes (ppr occ)) 2 (text "standing for" <+> quotes pp_hole_type_with_kind) , tyvars_msg, type_hole_hint ]+ ConstraintHole -> vcat [ hang (text "Found extra-constraints wildcard standing for")+ 2 (quotes $ pprType hole_ty) -- always kind constraint+ , tyvars_msg, type_hole_hint ] pp_hole_type_with_kind | isLiftedTypeKind hole_kind@@ -1477,7 +1483,7 @@ , report ] - | MTVU_Occurs <- occ_check_expand+ | CTE_Occurs <- occ_check_expand -- We report an "occurs check" even for a ~ F t a, where F is a type -- function; it's not insoluble (because in principle F could reduce) -- but we have certainly been unable to solve it@@ -1498,7 +1504,7 @@ ; mkErrorMsgFromCt ctxt ct $ mconcat [headline_msg, extra2, extra3, report] } - | MTVU_Bad <- occ_check_expand+ | CTE_Bad <- occ_check_expand = do { let msg = vcat [ text "Cannot instantiate unification variable" <+> quotes (ppr tv1) , hang (text "with a" <+> what <+> text "involving polytypes:") 2 (ppr ty2) ]@@ -1629,7 +1635,7 @@ eq_pred = ctEvPred ev orig = ctEvOrigin ev level = ctLocTypeOrKind_maybe (ctEvLoc ev) `orElse` TypeLevel- givens = [ given | given <- getUserGivens ctxt, not (ic_no_eqs given)]+ givens = [ given | given <- getUserGivens ctxt, ic_given_eqs given /= NoGivenEqs ] -- Keep only UserGivens that have some equalities. -- See Note [Suppress redundant givens during error reporting] @@ -1687,7 +1693,10 @@ redundant), so it's not terribly useful to report it in an error message. To accomplish this, we discard any Implications that do not bind any equalities by filtering the `givens` selected in `misMatchOrCND` (based on-the `ic_no_eqs` field of the Implication).+the `ic_given_eqs` field of the Implication). Note that we discard givens+that have no equalities whatsoever, but we want to keep ones with only *local*+equalities, as these may be helpful to the user in understanding what went+wrong. But this is not enough to avoid all redundant givens! Consider this example, from #15361:@@ -1700,7 +1709,7 @@ The (* ~ *) part arises due the kinds of (:~~:) being unified. More importantly, (* ~ *) is redundant, so we'd like not to report it. However, the Implication (* ~ *, a ~ b) /does/ bind an equality (as reported by its-ic_no_eqs field), so the test above will keep it wholesale.+ic_given_eqs field), so the test above will keep it wholesale. To refine this given, we apply mkMinimalBySCs on it to extract just the (a ~ b) part. This works because mkMinimalBySCs eliminates reflexive equalities in@@ -1742,7 +1751,7 @@ -- 'find' returns the binders of an InferSkol for 'tv', -- provided there is an intervening implication with- -- ic_no_eqs = False (i.e. a GADT match)+ -- ic_given_eqs /= NoGivenEqs (i.e. a GADT match) find [] _ _ = [] find (implic:implics) seen_eqs tv | tv `elem` ic_skols implic@@ -1750,7 +1759,7 @@ , seen_eqs = map fst prs | otherwise- = find implics (seen_eqs || not (ic_no_eqs implic)) tv+ = find implics (seen_eqs || ic_given_eqs implic /= NoGivenEqs) tv -------------------- misMatchMsg :: ReportErrCtxt -> Ct -> TcType -> TcType -> Report@@ -2728,15 +2737,11 @@ instances C (Maybe Int) and C (Maybe a) Since (F x) might turn into Int, this is an overlap situation, and-indeed (because of flattening) the main solver will have refrained+indeed the main solver will have refrained from solving. But by the time we get to error message generation, we've un-flattened the constraint. So we must *re*-flatten it before looking up in the instance environment, lest we only report one matching instance when in fact there are two.--Re-flattening is pretty easy, because we don't need to keep track of-evidence. We don't re-use the code in GHC.Tc.Solver.Canonical because that's in-the TcS monad, and we are in TcM here. Note [Kind arguments in error messages] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/Tc/Errors/Hole.hs view
@@ -22,7 +22,8 @@ import GHC.Core.Type import GHC.Core.DataCon import GHC.Types.Name-import GHC.Types.Name.Reader ( pprNameProvenance , GlobalRdrElt (..), globalRdrEnvElts )+import GHC.Types.Name.Reader ( pprNameProvenance , GlobalRdrElt (..)+ , globalRdrEnvElts, greMangledName, grePrintableName ) import GHC.Builtin.Names ( gHC_ERR ) import GHC.Types.Id import GHC.Types.Var.Set@@ -441,8 +442,7 @@ pprHoleFit _ (RawHoleFit sd) = sd pprHoleFit (HFDC sWrp sWrpVars sTy sProv sMs) (HoleFit {..}) = hang display 2 provenance- where name = getName hfCand- tyApp = sep $ zipWithEqual "pprHoleFit" pprArg vars hfWrap+ where tyApp = sep $ zipWithEqual "pprHoleFit" pprArg vars hfWrap where pprArg b arg = case binderArgFlag b of -- See Note [Explicit Case Statement for Specificity] (Invisible spec) -> case spec of@@ -471,7 +471,10 @@ holeVs = sep $ map (parens . (text "_" <+> dcolon <+>) . ppr) hfMatches holeDisp = if sMs then holeVs else sep $ replicate (length hfMatches) $ text "_"- occDisp = pprPrefixOcc name+ occDisp = case hfCand of+ GreHFCand gre -> pprPrefixOcc (grePrintableName gre)+ NameHFCand name -> pprPrefixOcc name+ IdHFCand id_ -> pprPrefixOcc id_ tyDisp = ppWhen sTy $ dcolon <+> ppr hfType has = not . null wrapDisp = ppWhen (has hfWrap && (sWrp || sWrpVars))@@ -490,7 +493,8 @@ provenance = ppWhen sProv $ parens $ case hfCand of GreHFCand gre -> pprNameProvenance gre- _ -> text "bound at" <+> ppr (getSrcLoc name)+ NameHFCand name -> text "bound at" <+> ppr (getSrcLoc name)+ IdHFCand id_ -> text "bound at" <+> ppr (getSrcLoc id_) getLocalBindings :: TidyEnv -> CtLoc -> TcM [Id] getLocalBindings tidy_orig ct_loc@@ -784,7 +788,7 @@ #if __GLASGOW_HASKELL__ <= 810 IdHFCand id -> idName id #endif- GreHFCand gre -> gre_name gre+ GreHFCand gre -> greMangledName gre NameHFCand name -> name discard_it = go subs seen maxleft ty elts keep_it eid eid_ty wrp ms = go (fit:subs) (extendVarSet seen eid)
compiler/GHC/Tc/Gen/App.hs view
@@ -86,17 +86,43 @@ a polytype. * When QL is done, we don't need to turn the un-filled-in- instantiation variables into unification variables -- they already- are!-- Moreover, all filled-in occurrences of instantiation variables- have been zonked away (see "Crucial step" in tcValArgs), and- so the rest of the type checker never sees a meta-type variable- filled in with a polytype. For the rest of the typechecker,- a meta type variable stands (only) for a monotype.+ instantiation variables into unification variables -- they+ already /are/ unification varibles! See also+ Note [Instantiation variables are short lived]. * We cleverly avoid the quadratic cost of QL, alluded to in the paper. See Note [Quick Look at value arguments]++Note [Instantiation variables are short lived]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+By the time QL is done, all filled-in occurrences of instantiation+variables have been zonked away (see "Crucial step" in tcValArgs),+and so the constraint /generator/ never subsequently sees a meta-type+variable filled in with a polytype -- a meta type variable stands+(only) for a monotype. See Section 4.3 "Applications and instantiation"+of the paper.++However, the constraint /solver/ can see a meta-type-variable filled+in with a polytype (#18987). Suppose+ f :: forall a. Dict a => [a] -> [a]+ xs :: [forall b. b->b]+and consider the call (f xs). QL will+* Instantiate f, with a := kappa, where kappa is an instantiation variable+* Emit a constraint (Dict kappa), via instantiateSigma, called from tcInstFun+* Do QL on the argument, to discover kappa := forall b. b->b++But by the time the third step has happened, the constraint has been+emitted into the monad. The constraint solver will later find it, and+rewrite it to (Dict (forall b. b->b)). That's fine -- the constraint+solver does no implicit instantiation (which is what makes it so+tricky to have foralls hiding inside unification variables), so there+is no difficulty with allowing those filled-in kappa's to persist.+(We could find them and zonk them away, but that would cost code and+execution time, for no purpose.)++Since the constraint solver does not do implicit instantiation (as the+constraint generator does), the fact that a unification variable might+stand for a polytype does not matter. -} @@ -263,6 +289,15 @@ -- Typecheck the value arguments ; tc_args <- tcValArgs do_ql tc_fun inst_args + -- Zonk the result type, to ensure that we substitute out+ -- any filled-in instantiation variable before calling tcWrapResultMono+ -- In the Check case, this isn't really necessary, becuase tcWrapResultMono+ -- just drops to tcUnify; but in the Infer case a filled-in instantiation+ -- variable might perhaps escape into the constraint generator. The safe+ -- thing to do is to any instantaition variables away.+ -- See Note [Instantiation variables are short lived]+ ; app_res_rho <- zonkQuickLook do_ql app_res_rho+ -- Special case for tagToEnum# ; if isTagToEnum rn_fun then tcTagToEnum rn_expr tc_fun tc_args app_res_rho exp_res_ty@@ -272,11 +307,29 @@ ; let tc_expr = rebuild tc_fun tc_args -- Wrap the result- -- NB: app_res_ty may be a polytype, via zonkQuickLook ; addFunResCtxt tc_fun tc_args app_res_rho exp_res_ty $- tcWrapResult rn_expr tc_expr app_res_rho exp_res_ty } }+ tcWrapResultMono rn_expr tc_expr app_res_rho exp_res_ty } } --------------------+wantQuickLook :: HsExpr GhcRn -> TcM Bool+-- GHC switches on impredicativity all the time for ($)+wantQuickLook (HsVar _ f) | unLoc f `hasKey` dollarIdKey = return True+wantQuickLook _ = xoptM LangExt.ImpredicativeTypes++zonkQuickLook :: Bool -> TcType -> TcM TcType+-- After all Quick Look unifications are done, zonk to ensure that all+-- instantation variables are substituted away+--+-- So far as the paper is concerned, this step applies+-- the poly-substitution Theta, learned by QL, so that we+-- "see" the polymorphism in that type+--+-- In implementation terms this ensures that no unification variable+-- linger on that have been filled in with a polytype+zonkQuickLook do_ql ty+ | do_ql = zonkTcType ty+ | otherwise = return ty+ -- zonkArg is used *only* during debug-tracing, to make it easier to -- see what is going on. For that reason, it is not a full zonk: add -- more if you need it.@@ -287,18 +340,13 @@ zonkArg arg = return arg -wantQuickLook :: HsExpr GhcRn -> TcM Bool--- GHC switches on impredicativity all the time for ($)-wantQuickLook (HsVar _ f) | unLoc f `hasKey` dollarIdKey = return True-wantQuickLook _ = xoptM LangExt.ImpredicativeTypes - ---------------- tcValArgs :: Bool -- Quick-look on? -> HsExpr GhcTc -- The function (for error messages) -> [HsExprArg 'TcpInst] -- Actual argument -> TcM [HsExprArg 'TcpTc] -- Resulting argument-tcValArgs quick_look fun args+tcValArgs do_ql fun args = go 1 args where go _ [] = return []@@ -321,8 +369,8 @@ -- (:) :: forall p. p->[p]->[p] -- Then Theta = [p :-> forall a. a->a], and we want -- to check 'e' with expected type (forall a. a->a)- arg_ty <- if quick_look then zonkTcType arg_ty- else return arg_ty+ -- See Note [Instantiation variables are short lived]+ arg_ty <- zonkQuickLook do_ql arg_ty -- Now check the argument ; arg' <- addErrCtxt (funAppCtxt fun (eValArgExpr arg) n) $@@ -907,7 +955,7 @@ * We must not make an occurs-check; we use occCheckExpand for that. -* metaTyVarUpdateOK also checks for various other things, including+* checkTypeEq also checks for various other things, including - foralls, and predicate types (which we want to allow here) - type families (relates to a very specific and exotic performance question, that is unlikely to bite here)@@ -1062,7 +1110,7 @@ vanilla_result = do { let expr' = rebuildPrefixApps fun args- ; tcWrapResult expr expr' app_res_ty res_ty }+ ; tcWrapResultMono expr expr' app_res_ty res_ty } check_enumeration ty' tc | isEnumerationTyCon tc = return ()
compiler/GHC/Tc/Gen/Arrow.hs view
@@ -89,14 +89,17 @@ -> ExpRhoType -- Expected type of whole proc expression -> TcM (LPat GhcTc, LHsCmdTop GhcTc, TcCoercion) -tcProc pat cmd exp_ty- = newArrowScope $- do { exp_ty <- expTypeToType exp_ty -- no higher-rank stuff with arrows+tcProc pat cmd@(L _ (HsCmdTop names _)) exp_ty+ = do { exp_ty <- expTypeToType exp_ty -- no higher-rank stuff with arrows ; (co, (exp_ty1, res_ty)) <- matchExpectedAppTy exp_ty ; (co1, (arr_ty, arg_ty)) <- matchExpectedAppTy exp_ty1+ -- start with the names as they are used to desugar the proc itself+ -- See #17423+ ; names' <- mapM (tcSyntaxName ProcOrigin arr_ty) names ; let cmd_env = CmdEnv { cmd_arr = arr_ty }- ; (pat', cmd') <- tcCheckPat ProcExpr pat (unrestricted arg_ty) $- tcCmdTop cmd_env cmd (unitTy, res_ty)+ ; (pat', cmd') <- newArrowScope+ $ tcCheckPat ProcExpr pat (unrestricted arg_ty)+ $ tcCmdTop cmd_env names' cmd (unitTy, res_ty) ; let res_co = mkTcTransCo co (mkTcAppCo co1 (mkTcNomReflCo res_ty)) ; return (pat', cmd', res_co) }@@ -115,7 +118,7 @@ data CmdEnv = CmdEnv {- cmd_arr :: TcType -- arrow type constructor, of kind *->*->*+ cmd_arr :: TcType -- ^ Arrow type constructor, of kind *->*->* } mkCmdArrTy :: CmdEnv -> TcTauType -> TcTauType -> TcTauType@@ -123,15 +126,15 @@ --------------------------------------- tcCmdTop :: CmdEnv+ -> CmdSyntaxTable GhcTc -- ^ Type-checked Arrow class methods (arr, (>>>), ...) -> LHsCmdTop GhcRn -> CmdType -> TcM (LHsCmdTop GhcTc) -tcCmdTop env (L loc (HsCmdTop names cmd)) cmd_ty@(cmd_stk, res_ty)+tcCmdTop env names (L loc (HsCmdTop _names cmd)) cmd_ty@(cmd_stk, res_ty) = setSrcSpan loc $- do { cmd' <- tcCmd env cmd cmd_ty- ; names' <- mapM (tcSyntaxName ProcOrigin (cmd_arr env)) names- ; return (L loc $ HsCmdTop (CmdTopTc cmd_stk res_ty names') cmd') }+ do { cmd' <- tcCmd env cmd cmd_ty+ ; return (L loc $ HsCmdTop (CmdTopTc cmd_stk res_ty names) cmd') } ---------------------------------------- tcCmd :: CmdEnv -> LHsCmd GhcRn -> CmdType -> TcM (LHsCmd GhcTc)@@ -319,12 +322,13 @@ where tc_cmd_arg :: LHsCmdTop GhcRn -> TcM (LHsCmdTop GhcTc, TcType)- tc_cmd_arg cmd+ tc_cmd_arg cmd@(L _ (HsCmdTop names _)) = do { arr_ty <- newFlexiTyVarTy arrowTyConKind ; stk_ty <- newFlexiTyVarTy liftedTypeKind ; res_ty <- newFlexiTyVarTy liftedTypeKind+ ; names' <- mapM (tcSyntaxName ProcOrigin arr_ty) names ; let env' = env { cmd_arr = arr_ty }- ; cmd' <- tcCmdTop env' cmd (stk_ty, res_ty)+ ; cmd' <- tcCmdTop env' names' cmd (stk_ty, res_ty) ; return (cmd', mkCmdArrTy env' (mkPairTy alphaTy stk_ty) res_ty) } -----------------------------------------------------------------
compiler/GHC/Tc/Gen/Bind.hs view
@@ -829,8 +829,7 @@ do { fam_envs <- tcGetFamInstEnvs ; let (_co, mono_ty') = normaliseType fam_envs Nominal mono_ty -- Unification may not have normalised the type,- -- (see Note [Lazy flattening] in GHC.Tc.Solver.Flatten) so do it- -- here to make it as uncomplicated as possible.+ -- so do it here to make it as uncomplicated as possible. -- Example: f :: [F Int] -> Bool -- should be rewritten to f :: [Char] -> Bool, if possible --
compiler/GHC/Tc/Gen/Export.hs view
@@ -27,6 +27,7 @@ import GHC.Data.Maybe import GHC.Utils.Misc (capitalise) import GHC.Data.FastString (fsLit)+import GHC.Driver.Env import GHC.Types.Unique.Set import GHC.Types.SrcLoc as SrcLoc@@ -146,7 +147,7 @@ Just (Just (acc', y)) -> (acc', Just y) _ -> (acc, Nothing) -type ExportOccMap = OccEnv (Name, IE GhcPs)+type ExportOccMap = OccEnv (GreName, IE GhcPs) -- Tracks what a particular exported OccName -- in an export list refers to, and which item -- it came from. It's illegal to export two distinct things@@ -172,7 +173,8 @@ -- thing (especially via 'module Foo' export item) do { ; dflags <- getDynFlags- ; let is_main_mod = mainModIs dflags == this_mod+ ; hsc_env <- getTopEnv+ ; let is_main_mod = mainModIs hsc_env == this_mod ; let default_main = case mainFunIs dflags of Just main_fun | is_main_mod -> mkUnqual varName (fsLit main_fun)@@ -246,13 +248,9 @@ -- Even though we don't check whether this is actually a data family -- only data families can locally define subordinate things (`ns` here) -- without locally defining (and instead importing) the parent (`n`)- fix_faminst (AvailTC n ns flds) =- let new_ns =- case ns of- [] -> [n]- (p:_) -> if p == n then ns else n:ns- in AvailTC n new_ns flds-+ fix_faminst avail@(AvailTC n ns)+ | availExportsDecl avail = avail+ | otherwise = AvailTC n (NormalGreName n:ns) fix_faminst avail = avail @@ -271,8 +269,8 @@ -- See Note [Avails of associated data families] expand_tyty_gre :: GlobalRdrElt -> [GlobalRdrElt]- expand_tyty_gre (gre@GRE { gre_name = me, gre_par = ParentIs p })- | isTyConName p, isTyConName me = [gre, gre{ gre_par = NoParent }]+ expand_tyty_gre (gre@GRE { gre_par = ParentIs p })+ | isTyConName p, isTyConName (greMangledName gre) = [gre, gre{ gre_par = NoParent }] expand_tyty_gre gre = [gre] imported_modules = [ imv_name imv@@ -353,10 +351,10 @@ (n, avail, flds) <- lookup_ie_all ie n' let name = unLoc n return (IEThingAll noExtField (replaceLWrappedName n' (unLoc n))- , AvailTC name (name:avail) flds)+ , availTC name (name:avail) flds) - lookup_ie ie@(IEThingWith _ l wc sub_rdrs _)+ lookup_ie ie@(IEThingWith _ l wc sub_rdrs) = do (lname, subs, avails, flds) <- addExportErrCtxt ie $ lookup_ie_with l sub_rdrs@@ -365,9 +363,9 @@ NoIEWildcard -> return (lname, [], []) IEWildcard _ -> lookup_ie_all ie l let name = unLoc lname- return (IEThingWith noExtField (replaceLWrappedName l name) wc subs- (flds ++ (map noLoc all_flds)),- AvailTC name (name : avails ++ all_avail)+ let flds' = flds ++ (map noLoc all_flds)+ return (IEThingWith flds' (replaceLWrappedName l name) wc subs,+ availTC name (name : avails ++ all_avail) (map unLoc flds ++ all_flds)) @@ -418,15 +416,7 @@ addUsedKids parent_rdr kid_gres = addUsedGREs (pickGREs parent_rdr kid_gres) classifyGREs :: [GlobalRdrElt] -> ([Name], [FieldLabel])-classifyGREs = partitionEithers . map classifyGRE--classifyGRE :: GlobalRdrElt -> Either Name FieldLabel-classifyGRE gre = case gre_par gre of- FldParent _ Nothing -> Right (FieldLabel (occNameFS (nameOccName n)) False n)- FldParent _ (Just lbl) -> Right (FieldLabel lbl True n)- _ -> Left n- where- n = gre_name gre+classifyGREs = partitionGreNames . map gre_name -- Renaming and typechecking of exports happens after everything else has -- been typechecked.@@ -527,11 +517,12 @@ NameNotFound -> do { ub <- reportUnboundName unboundName ; let l = getLoc n ; return (Left (L l (IEName (L l ub))))}- FoundFL fls -> return $ Right (L (getLoc n) fls)- FoundName par name -> do { checkPatSynParent spec_parent par name- ; return- $ Left (replaceLWrappedName n name) }- IncorrectParent p g td gs -> failWithDcErr p g td gs+ FoundChild par child -> do { checkPatSynParent spec_parent par child+ ; return $ case child of+ FieldGreName fl -> Right (L (getLoc n) fl)+ NormalGreName name -> Left (replaceLWrappedName n name)+ }+ IncorrectParent p c gs -> failWithDcErr p c gs -- Note: [Typing Pattern Synonym Exports]@@ -593,33 +584,30 @@ checkPatSynParent :: Name -- ^ Alleged parent type constructor -- User wrote T( P, Q ) -> Parent -- The parent of P we discovered- -> Name -- ^ Either a+ -> GreName -- ^ Either a -- a) Pattern Synonym Constructor -- b) A pattern synonym selector -> TcM () -- Fails if wrong parent checkPatSynParent _ (ParentIs {}) _ = return () -checkPatSynParent _ (FldParent {}) _- = return ()--checkPatSynParent parent NoParent mpat_syn+checkPatSynParent parent NoParent gname | isUnboundName parent -- Avoid an error cascade = return () | otherwise = do { parent_ty_con <- tcLookupTyCon parent- ; mpat_syn_thing <- tcLookupGlobal mpat_syn+ ; mpat_syn_thing <- tcLookupGlobal (greNameMangledName gname) -- 1. Check that the Id was actually from a thing associated with patsyns ; case mpat_syn_thing of AnId i | isId i , RecSelId { sel_tycon = RecSelPatSyn p } <- idDetails i- -> handle_pat_syn (selErr i) parent_ty_con p+ -> handle_pat_syn (selErr gname) parent_ty_con p AConLike (PatSynCon p) -> handle_pat_syn (psErr p) parent_ty_con p - _ -> failWithDcErr parent mpat_syn (ppr mpat_syn) [] }+ _ -> failWithDcErr parent gname [] } where psErr = exportErrCtxt "pattern synonym" selErr = exportErrCtxt "pattern synonym record selector"@@ -667,40 +655,47 @@ check_occs :: IE GhcPs -> ExportOccMap -> [AvailInfo] -> RnM ExportOccMap check_occs ie occs avails- -- 'names' and 'fls' are the entities specified by 'ie'- = foldlM check occs names_with_occs+ -- 'avails' are the entities specified by 'ie'+ = foldlM check occs children where- -- Each Name specified by 'ie', paired with the OccName used to- -- refer to it in the GlobalRdrEnv- -- (see Note [Representing fields in AvailInfo] in GHC.Types.Avail).- --- -- We check for export clashes using the selector Name, but need- -- the field label OccName for presenting error messages.- names_with_occs = availsNamesWithOccs avails+ children = concatMap availGreNames avails - check occs (name, occ)- = case lookupOccEnv occs name_occ of- Nothing -> return (extendOccEnv occs name_occ (name, ie))+ -- Check for distinct children exported with the same OccName (an error) or+ -- for duplicate exports of the same child (a warning).+ check :: ExportOccMap -> GreName -> RnM ExportOccMap+ check occs child+ = case try_insert occs child of+ Right occs' -> return occs' - Just (name', ie')- | name == name' -- Duplicate export+ Left (child', ie')+ | greNameMangledName child == greNameMangledName child' -- Duplicate export -- But we don't want to warn if the same thing is exported -- by two different module exports. See ticket #4478. -> do { warnIfFlag Opt_WarnDuplicateExports- (not (dupExport_ok name ie ie'))- (dupExportWarn occ ie ie')+ (not (dupExport_ok child ie ie'))+ (dupExportWarn child ie ie') ; return occs } | otherwise -- Same occ name but different names: an error -> do { global_env <- getGlobalRdrEnv ;- addErr (exportClashErr global_env occ name' name ie' ie) ;+ addErr (exportClashErr global_env child' child ie' ie) ; return occs }++ -- Try to insert a child into the map, returning Left if there is something+ -- already exported with the same OccName+ try_insert :: ExportOccMap -> GreName -> Either (GreName, IE GhcPs) ExportOccMap+ try_insert occs child+ = case lookupOccEnv occs name_occ of+ Nothing -> Right (extendOccEnv occs name_occ (child, ie))+ Just x -> Left x where- name_occ = nameOccName name+ -- For fields, we check for export clashes using the (OccName of the)+ -- selector Name+ name_occ = nameOccName (greNameMangledName child) -dupExport_ok :: Name -> IE GhcPs -> IE GhcPs -> Bool--- The Name is exported by both IEs. Is that ok?+dupExport_ok :: GreName -> IE GhcPs -> IE GhcPs -> Bool+-- The GreName is exported by both IEs. Is that ok? -- "No" iff the name is mentioned explicitly in both IEs -- or one of the IEs mentions the name *alone* -- "Yes" otherwise@@ -726,13 +721,13 @@ -- import Foo -- data instance T Int = TInt -dupExport_ok n ie1 ie2+dupExport_ok child ie1 ie2 = not ( single ie1 || single ie2 || (explicit_in ie1 && explicit_in ie2) ) where explicit_in (IEModuleContents {}) = False -- module M explicit_in (IEThingAll _ r)- = nameOccName n == rdrNameOcc (ieWrappedName $ unLoc r) -- T(..)+ = occName child == rdrNameOcc (ieWrappedName $ unLoc r) -- T(..) explicit_in _ = True single IEVar {} = True@@ -786,9 +781,9 @@ text "attempts to export constructors or class methods that are not visible here" ] -dupExportWarn :: OccName -> IE GhcPs -> IE GhcPs -> SDoc-dupExportWarn occ_name ie1 ie2- = hsep [quotes (ppr occ_name),+dupExportWarn :: GreName -> IE GhcPs -> IE GhcPs -> SDoc+dupExportWarn child ie1 ie2+ = hsep [quotes (ppr child), text "is exported by", quotes (ppr ie1), text "and", quotes (ppr ie2)] @@ -804,11 +799,11 @@ [_] -> text "Parent:" _ -> text "Parents:") <+> fsep (punctuate comma parents) -failWithDcErr :: Name -> Name -> SDoc -> [Name] -> TcM a-failWithDcErr parent thing thing_doc parents = do- ty_thing <- tcLookupGlobal thing+failWithDcErr :: Name -> GreName -> [Name] -> TcM a+failWithDcErr parent child parents = do+ ty_thing <- tcLookupGlobal (greNameMangledName child) failWithTc $ dcErrMsg parent (tyThingCategory' ty_thing)- thing_doc (map ppr parents)+ (ppr child) (map ppr parents) where tyThingCategory' :: TyThing -> String tyThingCategory' (AnId i)@@ -816,32 +811,37 @@ tyThingCategory' i = tyThingCategory i -exportClashErr :: GlobalRdrEnv -> OccName- -> Name -> Name+exportClashErr :: GlobalRdrEnv+ -> GreName -> GreName -> IE GhcPs -> IE GhcPs -> MsgDoc-exportClashErr global_env occ name1 name2 ie1 ie2+exportClashErr global_env child1 child2 ie1 ie2 = vcat [ text "Conflicting exports for" <+> quotes (ppr occ) <> colon- , ppr_export ie1' name1'- , ppr_export ie2' name2' ]+ , ppr_export child1' gre1' ie1'+ , ppr_export child2' gre2' ie2'+ ] where- ppr_export ie name = nest 3 (hang (quotes (ppr ie) <+> text "exports" <+>- quotes (ppr_name name))- 2 (pprNameProvenance (get_gre name)))+ occ = occName child1 + ppr_export child gre ie = nest 3 (hang (quotes (ppr ie) <+> text "exports" <+>+ quotes (ppr_name child))+ 2 (pprNameProvenance gre))+ -- DuplicateRecordFields means that nameOccName might be a mangled -- $sel-prefixed thing, in which case show the correct OccName alone- ppr_name name- | nameOccName name == occ = ppr name- | otherwise = ppr occ+ -- (but otherwise show the Name so it will have a module qualifier)+ ppr_name (FieldGreName fl) | flIsOverloaded fl = ppr fl+ | otherwise = ppr (flSelector fl)+ ppr_name (NormalGreName name) = ppr name -- get_gre finds a GRE for the Name, so that we can show its provenance- get_gre name- = fromMaybe (pprPanic "exportClashErr" (ppr name))- (lookupGRE_Name_OccName global_env name occ)- get_loc name = greSrcSpan (get_gre name)- (name1', ie1', name2', ie2') =- case SrcLoc.leftmost_smallest (get_loc name1) (get_loc name2) of- LT -> (name1, ie1, name2, ie2)- GT -> (name2, ie2, name1, ie1)+ gre1 = get_gre child1+ gre2 = get_gre child2+ get_gre child+ = fromMaybe (pprPanic "exportClashErr" (ppr child))+ (lookupGRE_GreName global_env child)+ (child1', gre1', ie1', child2', gre2', ie2') =+ case SrcLoc.leftmost_smallest (greSrcSpan gre1) (greSrcSpan gre2) of+ LT -> (child1, gre1, ie1, child2, gre2, ie2)+ GT -> (child2, gre2, ie2, child1, gre1, ie1) EQ -> panic "exportClashErr: clashing exports have idential location"
compiler/GHC/Tc/Gen/Expr.hs view
@@ -197,15 +197,12 @@ -- -- Some of these started life as a true expression hole "_". -- Others might simply be variables that accidentally have no binding site-tcExpr e@(HsUnboundVar _ occ) res_ty- = do { ty <- newOpenFlexiTyVarTy -- Allow Int# etc (#12531)- ; name <- newSysName occ- ; let ev = mkLocalId name Many ty- ; emitNewExprHole occ ev ty+tcExpr (HsUnboundVar _ occ) res_ty+ = do { ty <- expTypeToType res_ty -- Allow Int# etc (#12531)+ ; her <- emitNewExprHole occ ty ; tcEmitBindingUsage bottomUE -- Holes fit any usage environment -- (#18491)- ; tcWrapResultO (UnboundOccurrenceOf occ) e- (HsUnboundVar ev occ) ty res_ty }+ ; return (HsUnboundVar her occ) } tcExpr e@(HsLit x lit) res_ty = do { let lit_ty = hsLitType lit@@ -1356,12 +1353,12 @@ Just gre -> do { unless (null (tail xs)) $ do let L loc _ = hsRecFieldLbl (unLoc upd) setSrcSpan loc $ addUsedGRE True gre- ; lookupSelector (upd, gre_name gre) }+ ; lookupSelector (upd, greMangledName gre) } -- The field doesn't belong to this parent, so report -- an error but keep going through all the fields Nothing -> do { addErrTc (fieldNotInType p (unLoc (hsRecUpdFieldRdr (unLoc upd))))- ; lookupSelector (upd, gre_name (snd (head xs))) }+ ; lookupSelector (upd, greMangledName (snd (head xs))) } -- Given a (field update, selector name) pair, look up the -- selector to give a field update with an unambiguous Id
compiler/GHC/Tc/Gen/Head.hs view
@@ -493,11 +493,12 @@ = do { thing <- tcLookup sel_name ; case thing of ATcId { tct_id = id }- -> do { check_local_id occ id+ -> do { check_naughty occ id+ ; check_local_id id ; return id } AGlobal (AnId id)- -> do { check_global_id occ id+ -> do { check_naughty occ id ; return id } -- A global cannot possibly be ill-staged -- nor does it need the 'lifting' treatment@@ -545,7 +546,7 @@ Just gre -> do { addUsedGRE True gre- ; return (gre_name gre) } } } } }+ ; return (greMangledName gre) } } } } } -- This field name really is ambiguous, so add a suitable "ambiguous -- occurrence" error, then give up.@@ -596,10 +597,10 @@ ; mapM lookupParent gres } where lookupParent :: GlobalRdrElt -> RnM (RecSelParent, GlobalRdrElt)- lookupParent gre = do { id <- tcLookupId (gre_name gre)+ lookupParent gre = do { id <- tcLookupId (greMangledName gre) ; case recordSelectorTyCon_maybe id of Just rstc -> return (rstc, gre)- Nothing -> failWithTc (notSelector (gre_name gre)) }+ Nothing -> failWithTc (notSelector (greMangledName gre)) } fieldNotInType :: RecSelParent -> RdrName -> SDoc@@ -758,12 +759,14 @@ ; global_env <- getGlobalRdrEnv ; case thing of ATcId { tct_id = id }- -> do { check_local_id occ id+ -> do { check_local_id id ; return_id id } AGlobal (AnId id)- -> do { check_global_id occ id- ; return_id id }+ -> return_id id+ -- A global cannot possibly be ill-staged+ -- nor does it need the 'lifting' treatment+ -- Hence no checkTh stuff here AGlobal (AConLike cl) -> case cl of RealDataCon con -> return_data_con con@@ -798,8 +801,6 @@ = text "Illegal term-level use of the type constructor" <+> quotes (ppr (tyConName ty_con)) - occ = nameOccName id_name- return_id id = return (HsVar noExtField (noLoc id), idType id) return_data_con con@@ -845,19 +846,11 @@ , mkInvisForAllTys tvs $ mkInvisFunTysMany theta $ mkVisFunTys scaled_arg_tys res) } -check_local_id :: OccName -> Id -> TcM ()-check_local_id occ id- = do { check_naughty occ id -- See Note [HsVar: naughty record selectors]- ; checkThLocalId id+check_local_id :: Id -> TcM ()+check_local_id id+ = do { checkThLocalId id ; tcEmitBindingUsage $ unitUE (idName id) One } -check_global_id :: OccName -> Id -> TcM ()-check_global_id occ id- = check_naughty occ id -- See Note [HsVar: naughty record selectors]- -- A global cannot possibly be ill-staged- -- nor does it need the 'lifting' treatment- -- Hence no checkTh stuff here- check_naughty :: OccName -> TcId -> TcM () check_naughty lbl id | isNaughtyRecordSelector id = failWithTc (naughtyRecordSel lbl)@@ -868,15 +861,7 @@ text "non-bidirectional pattern synonym" <+> quotes (ppr name) <+> text "used in an expression" -{- Note [HsVar: naughty record selectors]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-All record selectors should really be HsRecFld (ambiguous or-unambiguous), but currently not all of them are: see #18452. So we-need to check for naughty record selectors in tc_infer_id, as well as-in tc_rec_sel_id.--Remove this code when fixing #18452.-+{- Note [Linear fields generalization] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As per Note [Polymorphisation of linear fields], linear field of data
compiler/GHC/Tc/Gen/HsType.hs view
@@ -66,6 +66,7 @@ -- Pattern type signatures tcHsPatSigType,+ HoleMode(..), -- Error messages funAppCtxt, addTyConFlavCtxt@@ -311,7 +312,7 @@ If an unsolved metavariable in a signature is not generalized (because we're not generalizing the construct -- e.g., pattern sig -- or because the metavars are constrained -- see kindGeneralizeSome)-we need to promote to maintain (WantedTvInv) of Note [TcLevel and untouchable type variables]+we need to promote to maintain (WantedTvInv) of Note [TcLevel invariants] in GHC.Tc.Utils.TcType. Note that promotion is identical in effect to generalizing and the reinstantiating with a fresh metavariable at the current level. So in some sense, we generalize *all* variables, but then re-instantiate@@ -329,7 +330,7 @@ the *body* of foo, though, we need to unify the type of x with the argument type of bar. At this point, the ambient TcLevel is 1, and spotting a matavariable with level 2 would violate the (WantedTvInv) invariant of-Note [TcLevel and untouchable type variables]. So, instead of kind-generalizing,+Note [TcLevel invariants]. So, instead of kind-generalizing, we promote the metavariable to level 1. This is all done in kindGeneralizeNone. -}@@ -819,6 +820,9 @@ | HM_VTA -- Visible type and kind application: -- f @(Maybe _) -- Maybe @(_ -> _)+ | HM_TyAppPat -- Visible type applications in patterns:+ -- foo (Con @_ @t x) = ...+ -- case x of Con @_ @t v -> ... mkMode :: TypeOrKind -> TcTyMode mkMode tyki = TcTyMode { mode_tyki = tyki, mode_holes = Nothing }@@ -835,9 +839,10 @@ , mode_holes = Just (lvl,hm) }) } instance Outputable HoleMode where- ppr HM_Sig = text "HM_Sig"- ppr HM_FamPat = text "HM_FamPat"- ppr HM_VTA = text "HM_VTA"+ ppr HM_Sig = text "HM_Sig"+ ppr HM_FamPat = text "HM_FamPat"+ ppr HM_VTA = text "HM_VTA"+ ppr HM_TyAppPat = text "HM_TyAppPat" instance Outputable TcTyMode where ppr (TcTyMode { mode_tyki = tyki, mode_holes = hm })@@ -942,8 +947,8 @@ tc_infer_hs_type mode (HsDocTy _ ty _) = tc_infer_lhs_type mode ty --- See Note [Typechecking NHsCoreTys]-tc_infer_hs_type _ (XHsType (NHsCoreTy ty))+-- See Note [Typechecking HsCoreTys]+tc_infer_hs_type _ (XHsType ty) = do env <- getLclEnv -- Raw uniques since we go from NameEnv to TvSubstEnv. let subst_prs :: [(Unique, TcTyVar)]@@ -967,21 +972,21 @@ ; return (ty', kv) } {--Note [Typechecking NHsCoreTys]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-NHsCoreTy is an escape hatch that allows embedding Core Types in HsTypes.-As such, there's not much to be done in order to typecheck an NHsCoreTy,+Note [Typechecking HsCoreTys]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+HsCoreTy is an escape hatch that allows embedding Core Types in HsTypes.+As such, there's not much to be done in order to typecheck an HsCoreTy, since it's already been typechecked to some extent. There is one thing that we must do, however: we must substitute the type variables from the tcl_env. To see why, consider GeneralizedNewtypeDeriving, which is one of the main-clients of NHsCoreTy (example adapted from #14579):+clients of HsCoreTy (example adapted from #14579): newtype T a = MkT a deriving newtype Eq This will produce an InstInfo GhcPs that looks roughly like this: instance forall a_1. Eq a_1 => Eq (T a_1) where- (==) = coerce @( a_1 -> a_1 -> Bool) -- The type within @(...) is an NHsCoreTy+ (==) = coerce @( a_1 -> a_1 -> Bool) -- The type within @(...) is an HsCoreTy @(T a_1 -> T a_1 -> Bool) -- So is this (==) @@ -997,9 +1002,9 @@ To ensure that the body of this instance is well scoped, every occurrence of the `a` type variable should refer to a_2, the new skolem. However, the-NHsCoreTys mention a_1, not a_2. Luckily, the tcl_env provides exactly the+HsCoreTys mention a_1, not a_2. Luckily, the tcl_env provides exactly the substitution we need ([a_1 :-> a_2]) to fix up the scoping. We apply this-substitution to each NHsCoreTy and all is well:+substitution to each HsCoreTy and all is well: instance forall a_2. Eq a_2 => Eq (T a_2) where (==) = coerce @( a_2 -> a_2 -> Bool)@@ -1189,6 +1194,11 @@ = do { checkWiredInTyCon typeSymbolKindCon ; checkExpectedKind rn_ty (mkStrLitTy s) typeSymbolKind exp_kind } +--------- Wildcards++tc_hs_type mode ty@(HsWildCardTy _) ek+ = tcAnonWildCardOcc NoExtraConstraint mode ty ek+ --------- Potentially kind-polymorphic types: call the "up" checker -- See Note [Future-proofing the type checker] tc_hs_type mode ty@(HsTyVar {}) ek = tc_infer_hs_type_ek mode ty ek@@ -1196,8 +1206,7 @@ tc_hs_type mode ty@(HsAppKindTy{}) ek = tc_infer_hs_type_ek mode ty ek tc_hs_type mode ty@(HsOpTy {}) ek = tc_infer_hs_type_ek mode ty ek tc_hs_type mode ty@(HsKindSig {}) ek = tc_infer_hs_type_ek mode ty ek-tc_hs_type mode ty@(XHsType (NHsCoreTy{})) ek = tc_infer_hs_type_ek mode ty ek-tc_hs_type mode ty@(HsWildCardTy _) ek = tcAnonWildCardOcc mode ty ek+tc_hs_type mode ty@(XHsType {}) ek = tc_infer_hs_type_ek mode ty ek {- Note [Variable Specificity and Forall Visibility]@@ -2071,8 +2080,9 @@ ; return tyvar } ----------------------------tcAnonWildCardOcc :: TcTyMode -> HsType GhcRn -> Kind -> TcM TcType-tcAnonWildCardOcc (TcTyMode { mode_holes = Just (hole_lvl, hole_mode) })+tcAnonWildCardOcc :: IsExtraConstraint+ -> TcTyMode -> HsType GhcRn -> Kind -> TcM TcType+tcAnonWildCardOcc is_extra (TcTyMode { mode_holes = Just (hole_lvl, hole_mode) }) ty exp_kind -- hole_lvl: see Note [Checking partial type signatures] -- esp the bullet on nested forall types@@ -2086,7 +2096,7 @@ ; traceTc "tcAnonWildCardOcc" (ppr hole_lvl <+> ppr emit_holes) ; when emit_holes $- emitAnonTypeHole wc_tv+ emitAnonTypeHole is_extra wc_tv -- Why the 'when' guard? -- See Note [Wildcards in visible kind application] @@ -2098,16 +2108,18 @@ where -- See Note [Wildcard names] wc_nm = case hole_mode of- HM_Sig -> "w"- HM_FamPat -> "_"- HM_VTA -> "w"+ HM_Sig -> "w"+ HM_FamPat -> "_"+ HM_VTA -> "w"+ HM_TyAppPat -> "_" emit_holes = case hole_mode of HM_Sig -> True HM_FamPat -> False HM_VTA -> False+ HM_TyAppPat -> False -tcAnonWildCardOcc mode ty _+tcAnonWildCardOcc _ mode ty _ -- mode_holes is Nothing. Should not happen, because renamer -- should already have rejected holes in unexpected places = pprPanic "tcWildCardOcc" (ppr mode $$ ppr ty)@@ -2426,7 +2438,7 @@ -- ^^^^^^^^^ -- We do it here because at this point the environment has been -- extended with both 'implicit_tcv_prs' and 'explicit_tv_prs'.- ; ctx_k <- kc_res_ki+ ; ctx_k <- kc_res_ki ; m_res_ki <- case ctx_k of AnyKind -> return Nothing _ -> Just <$> newExpectedKind ctx_k@@ -2454,12 +2466,12 @@ ; return (invis_binders, r_ki) } - -- Zonk the implicitly quantified variables.- ; implicit_tvs <- mapM zonkTcTyVarToTyVar implicit_tvs- -- Convert each invisible TyCoBinder to TyConBinder for tyConBinders. ; invis_tcbs <- mapM invis_to_tcb invis_binders + -- Zonk the implicitly quantified variables.+ ; implicit_tvs <- mapM zonkTcTyVarToTyVar implicit_tvs+ -- Build the final, generalized TcTyCon ; let tcbs = vis_tcbs ++ invis_tcbs implicit_tv_prs = implicit_nms `zip` implicit_tvs@@ -2577,35 +2589,35 @@ in splitInvisPiTysN n_inst sig_ki -- A quantifier from a kind signature zipped with a user-written binder for it.-data ZippedBinder =- ZippedBinder TyBinder (Maybe (LHsTyVarBndr () GhcRn))+data ZippedBinder = ZippedBinder TyBinder (Maybe (LHsTyVarBndr () GhcRn)) -- See Note [Arity inference in kcCheckDeclHeader_sig] zipBinders- :: Kind -- kind signature- -> [LHsTyVarBndr () GhcRn] -- user-written binders- -> ([ZippedBinder], -- zipped binders- [LHsTyVarBndr () GhcRn], -- remaining user-written binders- Kind) -- remainder of the kind signature-zipBinders = zip_binders []+ :: Kind -- Kind signature+ -> [LHsTyVarBndr () GhcRn] -- User-written binders+ -> ( [ZippedBinder] -- Zipped binders+ , [LHsTyVarBndr () GhcRn] -- Leftover user-written binders+ , Kind ) -- Remainder of the kind signature+zipBinders = zip_binders [] emptyTCvSubst where- zip_binders acc ki [] = (reverse acc, [], ki)- zip_binders acc ki (b:bs) =- case tcSplitPiTy_maybe ki of- Nothing -> (reverse acc, b:bs, ki)- Just (tb, ki') ->- let- (zb, bs') | zippable = (ZippedBinder tb (Just b), bs)- | otherwise = (ZippedBinder tb Nothing, b:bs)- zippable =- case tb of- Named (Bndr _ (Invisible _)) -> False- Named (Bndr _ Required) -> True- Anon InvisArg _ -> False- Anon VisArg _ -> True- in- zip_binders (zb:acc) ki' bs'+ -- subst: we substitute as we go, to ensure that the resulting+ -- binders in the [ZippedBndr] all have distinct uniques.+ -- If not, the TyCon may get multiple binders with the same unique,+ -- which results in chaos (see #19092,3,4)+ -- (The incoming kind might be forall k. k -> forall k. k -> Type+ -- where those two k's have the same unique. Without the substitution+ -- we'd get a repeated 'k'.)+ zip_binders acc subst ki bs+ | (b:bs') <- bs -- Stop as soon as 'bs' becomes empty+ , Just (tb,ki') <- tcSplitPiTy_maybe ki+ , let (subst', tb') = substTyCoBndr subst tb+ = if isInvisibleBinder tb+ then zip_binders (ZippedBinder tb' Nothing : acc) subst' ki' bs+ else zip_binders (ZippedBinder tb' (Just b) : acc) subst' ki' bs' + | otherwise+ = (reverse acc, bs, substTy subst ki)+ tooManyBindersErr :: Kind -> [LHsTyVarBndr () GhcRn] -> SDoc tooManyBindersErr ki bndrs = hang (text "Not a function kind:")@@ -2814,24 +2826,6 @@ although T3 is really polymorphic-recursive too. Perhaps we should somehow reject that. -Note [Kind-checking tyvar binders for associated types]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When kind-checking the type-variable binders for associated- data/newtype decls- family decls-we behave specially for type variables that are already in scope;-that is, bound by the enclosing class decl. This is done in-kcLHsQTyVarBndrs:- * The use of tcImplicitQTKBndrs- * The tcLookupLocal_maybe code in kc_hs_tv--See Note [Associated type tyvar names] in GHC.Core.Class and- Note [TyVar binders for associated decls] in GHC.Hs.Decls--We must do the same for family instance decls, where the in-scope-variables may be bound by the enclosing class instance decl.-Hence the use of tcImplicitQTKBndrs in tcFamTyPatsAndGen.- Note [Kind variable ordering for associated types] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ What should be the kind of `T` in the following example? (#15591)@@ -2981,7 +2975,7 @@ -> TcM a -> TcM (HsOuterSigTyVarBndrs GhcTc, a) -- Do not push level; do not make implication constraint; use Tvs -- Two major clients of this "bind-only" path are:--- Note [Kind-checking for GADTs] in TyCl+-- Note [Using TyVarTvs for kind-checking GADTs] in GHC.Tc.TyCl -- Note [Checking partial type signatures] bindOuterSigTKBndrs_Tv_M mode = bindOuterTKBndrsX (smVanilla { sm_clone = True, sm_tvtv = True@@ -3294,8 +3288,8 @@ When kind-checking T, we give (a :: kappa1). Then: - In kcConDecl we make a TyVarTv unification variable kappa2 for k2- (as described in Note [Kind-checking for GADTs], even though this- example is an existential)+ (as described in Note [Using TyVarTvs for kind-checking GADTs],+ even though this example is an existential) - So we get (b :: kappa2) via bindExplicitTKBndrs_Tv - We end up unifying kappa1 := kappa2, because of the (SameKind a b) @@ -3805,7 +3799,7 @@ | Just (hs_theta1, hs_ctxt_last) <- snocView hs_theta , L wc_loc ty@(HsWildCardTy _) <- ignoreParens hs_ctxt_last = do { wc_tv_ty <- setSrcSpan wc_loc $- tcAnonWildCardOcc mode ty constraintKind+ tcAnonWildCardOcc YesExtraConstraint mode ty constraintKind ; theta <- mapM (tc_lhs_pred mode) hs_theta1 ; return (theta, Just wc_tv_ty) } | otherwise@@ -3934,6 +3928,8 @@ Result works fine, but it may eventually bite us. +See also Note [Do not simplify ConstraintHoles] in GHC.Tc.Solver for+information about how these are printed. ************************************************************************ * *@@ -3942,7 +3938,9 @@ ********************************************************************* -} tcHsPatSigType :: UserTypeCtxt+ -> HoleMode -- HM_Sig when in a SigPat, HM_TyAppPat when in a ConPat checking type applications. -> HsPatSigType GhcRn -- The type signature+ -> ContextKind -- What kind is expected -> TcM ( [(Name, TcTyVar)] -- Wildcards , [(Name, TcTyVar)] -- The new bit of type environment, binding -- the scoped type variables@@ -3954,12 +3952,13 @@ -- -- This may emit constraints -- See Note [Recipe for checking a signature]-tcHsPatSigType ctxt+tcHsPatSigType ctxt hole_mode (HsPS { hsps_ext = HsPSRn { hsps_nwcs = sig_wcs, hsps_imp_tvs = sig_ns } , hsps_body = hs_ty })+ ctxt_kind = addSigCtxt ctxt hs_ty $ do { sig_tkv_prs <- mapM new_implicit_tv sig_ns- ; mode <- mkHoleMode TypeLevel HM_Sig+ ; mode <- mkHoleMode TypeLevel hole_mode ; (wcs, sig_ty) <- addTypeCtxt hs_ty $ solveEqualities "tcHsPatSigType" $@@ -3967,7 +3966,7 @@ -- and c.f #16033 bindNamedWildCardBinders sig_wcs $ \ wcs -> tcExtendNameTyVarEnv sig_tkv_prs $- do { ek <- newOpenTypeKind+ do { ek <- newExpectedKind ctxt_kind ; sig_ty <- tc_lhs_type mode hs_ty ek ; return (wcs, sig_ty) }
compiler/GHC/Tc/Gen/Pat.hs view
@@ -53,6 +53,7 @@ import GHC.Tc.Types.Evidence import GHC.Tc.Types.Origin import GHC.Core.TyCon+import GHC.Core.Type import GHC.Core.DataCon import GHC.Core.PatSyn import GHC.Core.ConLike@@ -66,7 +67,7 @@ import GHC.Utils.Panic import qualified GHC.LanguageExtensions as LangExt import Control.Arrow ( second )-import Control.Monad ( when )+import Control.Monad import GHC.Data.List.SetOps ( getNth ) {-@@ -554,7 +555,7 @@ ------------------------ -- Data constructors- ConPat NoExtField con arg_pats ->+ ConPat _ con arg_pats -> tcConPat penv con pat_ty arg_pats thing_inside ------------------------@@ -736,7 +737,7 @@ HsWrapper) -- Coercion due to unification with actual ty -- Of shape: res_ty ~ sig_ty tcPatSig in_pat_bind sig res_ty- = do { (sig_wcs, sig_tvs, sig_ty) <- tcHsPatSigType PatSigCtxt sig+ = do { (sig_wcs, sig_tvs, sig_ty) <- tcHsPatSigType PatSigCtxt HM_Sig sig OpenKind -- sig_tvs are the type variables free in 'sig', -- and not already in scope. These are the ones -- that should be brought into scope@@ -890,20 +891,18 @@ ; let all_arg_tys = eqSpecPreds eq_spec ++ theta ++ (map scaledThing arg_tys) ; checkExistentials ex_tvs all_arg_tys penv - ; tenv <- instTyVarsWith PatOrigin univ_tvs ctxt_res_tys+ ; tenv1 <- instTyVarsWith PatOrigin univ_tvs ctxt_res_tys -- NB: Do not use zipTvSubst! See #14154 -- We want to create a well-kinded substitution, so -- that the instantiated type is well-kinded - ; (tenv, ex_tvs') <- tcInstSuperSkolTyVarsX tenv ex_tvs+ ; (tenv, ex_tvs') <- tcInstSuperSkolTyVarsX tenv1 ex_tvs -- Get location from monad, not from ex_tvs -- This freshens: See Note [Freshen existentials]-- ; let -- pat_ty' = mkTyConApp tycon ctxt_res_tys- -- pat_ty' is type of the actual constructor application- -- pat_ty' /= pat_ty iff coi /= IdCo+ -- Why "super"? See Note [Binding when lookup up instances]+ -- in GHC.Core.InstEnv. - arg_tys' = substScaledTys tenv arg_tys+ ; let arg_tys' = substScaledTys tenv arg_tys pat_mult = scaledMult pat_ty_scaled arg_tys_scaled = map (scaleScaled pat_mult) arg_tys' @@ -920,7 +919,7 @@ then do { -- The common case; no class bindings etc -- (see Note [Arrows and patterns]) (arg_pats', res) <- tcConArgs (RealDataCon data_con) arg_tys_scaled- penv arg_pats thing_inside+ tenv penv arg_pats thing_inside ; let res_pat = ConPat { pat_con = header , pat_args = arg_pats' , pat_con_ext = ConPatTc@@ -956,7 +955,7 @@ ; given <- newEvVars theta' ; (ev_binds, (arg_pats', res)) <- checkConstraints skol_info ex_tvs' given $- tcConArgs (RealDataCon data_con) arg_tys_scaled penv arg_pats thing_inside+ tcConArgs (RealDataCon data_con) arg_tys_scaled tenv penv arg_pats thing_inside ; let res_pat = ConPat { pat_con = header@@ -1017,7 +1016,7 @@ ; traceTc "checkConstraints {" Outputable.empty ; (ev_binds, (arg_pats', res)) <- checkConstraints skol_info ex_tvs' prov_dicts' $- tcConArgs (PatSynCon pat_syn) arg_tys_scaled penv arg_pats thing_inside+ tcConArgs (PatSynCon pat_syn) arg_tys_scaled tenv penv arg_pats thing_inside ; traceTc "checkConstraints }" (ppr ev_binds) ; let res_pat = ConPat { pat_con = L con_span $ PatSynCon pat_syn@@ -1123,17 +1122,84 @@ error messages; it's a purely internal thing -} -tcConArgs :: ConLike -> [Scaled TcSigmaType]- -> Checker (HsConPatDetails GhcRn) (HsConPatDetails GhcTc)+{-+Note [Typechecking type applications in patterns]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+How should we typecheck type applications in patterns, such as+ f :: Either (Maybe a) [b] -> blah+ f (Left @x @[y] (v::Maybe x)) = blah -tcConArgs con_like arg_tys penv con_args thing_inside = case con_args of- PrefixCon arg_pats -> do+It's quite straightforward, and very similar to the treatment of+pattern signatures.++* Step 1: bind the newly-in-scope type variables x and y to fresh+ unification variables, say x0 and y0.++* Step 2: typecheck those type arguments, @x and @[y], to get the+ types x0 and [y0].++* Step 3: Unify those types with the type arguments we expect,+ in this case (Maybe a) and [b]. These unifications will+ (perhaps after the constraint solver has done its work)+ unify x0 := Maybe a+ y0 := b+ Thus we learn that x stands for (Maybe a) and y for b.++Wrinkles:++* Surprisingly, we can discard the coercions arising from+ these unifications. The *only* thing the unification does is+ to side-effect those unification variables, so that we know+ what type x and y stand for; and cause an error if the equality+ is not soluble. It's a bit like a Derived constraint arising+ from a functional dependency.++* Exactly the same works for existential arguments+ data T where+ MkT :: a -> a -> T+ f :: T -> blah+ f (MkT @x v w) = ...+ Here we create a fresh unification variable x0 for x, and+ unify it with the fresh existential variable bound by the pattern.++* Note that both here and in pattern signatures the unification may+ not even end up unifying the variable. For example+ type S a b = a+ f :: Maybe a -> Bool+ f (Just @(S a b) x) = True :: b+ In Step 3 we will unify (S a0 b0 ~ a), which succeeds, but has no+ effect on the unification variable b0, to which 'b' is bound.+ Later, in the RHS, we find that b0 must be Bool, and unify it there.+ All is fine.+-}++tcConArgs :: ConLike+ -> [Scaled TcSigmaType]+ -> 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+ PrefixCon type_args arg_pats -> do { checkTc (con_arity == no_of_args) -- Check correct arity (arityErr (text "constructor") con_like con_arity no_of_args)++ ; let con_binders = conLikeUserTyVarBinders con_like+ ; checkTc (type_args `leLength` con_binders)+ (conTyArgArityErr con_like (length con_binders) (length type_args))+ ; let pats_w_tys = zipEqual "tcConArgs" arg_pats arg_tys- ; (arg_pats', res) <- tcMultiple tcConArg penv pats_w_tys- thing_inside- ; return (PrefixCon arg_pats', res) }+ ; (type_args', (arg_pats', res))+ <- tcMultiple tcConTyArg penv type_args $+ tcMultiple tcConArg penv pats_w_tys thing_inside++ -- This unification is straight from Figure 7 of+ -- "Type Variables in Patterns", Haskell'18+ ; _ <- zipWithM (unifyType Nothing) type_args' (substTyVars tenv $+ binderVars con_binders)+ -- OK to drop coercions here. These unifications are all about+ -- guiding inference based on a user-written type annotation+ -- See Note [Typechecking type applications in patterns]++ ; return (PrefixCon type_args arg_pats', res) } where con_arity = conLikeArity con_like no_of_args = length arg_pats@@ -1188,6 +1254,22 @@ -- dataConFieldLabels will be empty (and each field in the pattern -- will generate an error below). +tcConTyArg :: Checker (HsPatSigType GhcRn) TcType+tcConTyArg penv rn_ty thing_inside+ = do { (sig_wcs, sig_ibs, arg_ty) <- tcHsPatSigType TypeAppCtxt HM_TyAppPat rn_ty AnyKind+ -- AnyKind is a bit suspect: it really should be the kind gotten+ -- from instantiating the constructor type. But this would be+ -- hard to get right, because earlier type patterns might influence+ -- the kinds of later patterns. In any case, it all gets checked+ -- by the calls to unifyType in tcConArgs, which will also unify+ -- kinds.+ ; when (not (null sig_ibs) && inPatBind penv) $+ addErr (text "Binding type variables is not allowed in pattern bindings")+ ; result <- tcExtendNameTyVarEnv sig_wcs $+ tcExtendNameTyVarEnv sig_ibs $+ thing_inside+ ; return (arg_ty, result) }+ tcConArg :: Checker (LPat GhcRn, Scaled TcSigmaType) (LPat GhcTc) tcConArg penv (arg_pat, Scaled arg_mult arg_ty) = tc_lpat (Scaled arg_mult (mkCheckExpType arg_ty)) penv arg_pat@@ -1208,6 +1290,14 @@ -- NB: inst_tys can be longer than the univ tyvars -- because the constructor might have existentials inst_theta = substTheta tenv stupid_theta++conTyArgArityErr :: ConLike+ -> Int -- expected # of arguments+ -> Int -- actual # of arguments+ -> SDoc+conTyArgArityErr con_like expected_number actual_number+ = text "Too many type arguments in constructor pattern for" <+> quotes (ppr con_like) $$+ text "Expected no more than" <+> ppr expected_number <> semi <+> text "got" <+> ppr actual_number {- Note [Arrows and patterns]
compiler/GHC/Tc/Gen/Rule.hs view
@@ -229,7 +229,7 @@ -- If there's an explicit forall, the renamer would have already reported an -- error for each out-of-scope type variable used = do { let ctxt = RuleSigCtxt name- ; (_ , tvs, id_ty) <- tcHsPatSigType ctxt rn_ty+ ; (_ , tvs, id_ty) <- tcHsPatSigType ctxt HM_Sig rn_ty OpenKind ; let id = mkLocalId name Many id_ty -- See Note [Typechecking pattern signature binders] in GHC.Tc.Gen.HsType
compiler/GHC/Tc/Gen/Sig.hs view
@@ -291,7 +291,7 @@ HsTyLit{} -> True HsTyVar{} -> True HsStarTy{} -> True- XHsType (NHsCoreTy{}) -> True -- Core type, which does not have any wildcard+ XHsType{} -> True -- HsCoreTy, which does not have any wildcard gos = all go
compiler/GHC/Tc/Gen/Splice.hs view
@@ -1443,7 +1443,7 @@ -- must error before proceeding to typecheck the -- renamed type, as that will result in GHC -- internal errors (#13837).- rnImplicitBndrs Nothing tv_rdrs $ \ tv_names ->+ rnImplicitTvOccs Nothing tv_rdrs $ \ tv_names -> do { (rn_ty, fvs) <- rnLHsType doc rdr_ty ; return ((tv_names, rn_ty), fvs) }
compiler/GHC/Tc/Instance/Family.hs view
@@ -523,7 +523,7 @@ -- It is only used by the type inference engine (specifically, when -- solving representational equality), and hence it is careful to unwrap -- only if the relevant data constructor is in scope. That's why--- it get a GlobalRdrEnv argument.+-- it gets a GlobalRdrEnv argument. -- -- It is careful not to unwrap data/newtype instances if it can't -- continue unwrapping. Such care is necessary for proper error
compiler/GHC/Tc/Instance/Typeable.hs view
@@ -40,7 +40,7 @@ import GHC.Driver.Session import GHC.Data.Bag import GHC.Types.Var ( VarBndr(..) )-import GHC.Core.Map+import GHC.Core.Map.Type import GHC.Settings.Constants import GHC.Utils.Fingerprint(Fingerprint(..), fingerprintString, fingerprintFingerprints) import GHC.Utils.Outputable
compiler/GHC/Tc/Module.hs view
@@ -1491,7 +1491,7 @@ foe_binds ; fo_gres = fi_gres `unionBags` foe_gres- ; fo_fvs = foldr (\gre fvs -> fvs `addOneFV` gre_name gre)+ ; fo_fvs = foldr (\gre fvs -> fvs `addOneFV` greMangledName gre) emptyFVs fo_gres ; sig_names = mkNameSet (collectHsValBinders hs_val_binds)@@ -1556,11 +1556,11 @@ where isLocalDef = gre_lcl x == True -- Names are identical ...- nameClashes = nameOccName (gre_name x) == nameOccName name+ nameClashes = nameOccName (greMangledName x) == nameOccName name -- ... but not the actual definitions, because we don't want to -- warn about a bad definition of e.g. <> in Data.Semigroup, which -- is the (only) proper place where this should be defined- isNotInProperModule = gre_name x /= name+ isNotInProperModule = greMangledName x /= name -- List of all offending definitions clashingElts :: [GlobalRdrElt]@@ -1569,9 +1569,9 @@ ; traceTc "tcPreludeClashWarn/prelude_functions" (hang (ppr name) 4 (sep [ppr clashingElts])) - ; let warn_msg x = addWarnAt (Reason warnFlag) (nameSrcSpan (gre_name x)) (hsep+ ; let warn_msg x = addWarnAt (Reason warnFlag) (nameSrcSpan (greMangledName x)) (hsep [ text "Local definition of"- , (quotes . ppr . nameOccName . gre_name) x+ , (quotes . ppr . nameOccName . greMangledName) x , text "clashes with a future Prelude name." ] $$ text "This will become an error in a future release." )@@ -1744,13 +1744,13 @@ -> TcM TcGblEnv -- If we are in module Main, check that 'main' is defined and exported. checkMain explicit_mod_hdr export_ies- = do { dflags <- getDynFlags+ = do { hsc_env <- getTopEnv ; tcg_env <- getGblEnv- ; check_main dflags tcg_env explicit_mod_hdr export_ies }+ ; check_main hsc_env tcg_env explicit_mod_hdr export_ies } -check_main :: DynFlags -> TcGblEnv -> Bool -> Maybe (Located [LIE GhcPs])+check_main :: HscEnv -> TcGblEnv -> Bool -> Maybe (Located [LIE GhcPs]) -> TcM TcGblEnv-check_main dflags tcg_env explicit_mod_hdr export_ies+check_main hsc_env tcg_env explicit_mod_hdr export_ies | mod /= main_mod = traceTc "checkMain not" (ppr main_mod <+> ppr mod) >> return tcg_env@@ -1791,8 +1791,9 @@ addAmbiguousNameErr main_fn -- issue error msg return tcg_env where+ dflags = hsc_dflags hsc_env mod = tcg_mod tcg_env- main_mod = mainModIs dflags+ main_mod = mainModIs hsc_env main_mod_nm = moduleName main_mod main_fn = getMainFun dflags occ_main_fn = occName main_fn@@ -2488,7 +2489,7 @@ let occIO = lookupOccEnv rdrEnv (mkOccName tcName ty) case occIO of Just [n] -> do- let name = gre_name n+ let name = greMangledName n ghciClass <- tcLookupClass ghciIoClassName userTyCon <- tcLookupTyCon name let userTy = mkTyConApp userTyCon []@@ -2856,7 +2857,7 @@ unqual_mods = [ nameModule name | gre <- globalRdrEnvElts (ic_rn_gbl_env ictxt)- , let name = gre_name gre+ , let name = greMangledName gre , nameIsFromExternalPackage home_unit name , isTcOcc (nameOccName name) -- Types and classes only , unQualOK gre ] -- In scope unqualified@@ -2880,7 +2881,7 @@ tcDump :: TcGblEnv -> TcRn () tcDump env = do { dflags <- getDynFlags ;- unit_state <- unitState <$> getDynFlags ;+ unit_state <- hsc_units <$> getTopEnv ; -- Dump short output if -ddump-types or -ddump-tc when (dopt Opt_D_dump_types dflags || dopt Opt_D_dump_tc dflags)
compiler/GHC/Tc/Plugin.hs view
@@ -80,7 +80,6 @@ import GHC.Driver.Env import GHC.Utils.Outputable import GHC.Core.Type-import GHC.Core.Coercion ( BlockSubstFlag(..) ) import GHC.Types.Id import GHC.Core.InstEnv import GHC.Data.FastString@@ -181,7 +180,7 @@ -- | Create a fresh coercion hole. newCoercionHole :: PredType -> TcPluginM CoercionHole-newCoercionHole = unsafeTcPluginTcM . TcM.newCoercionHole YesBlockSubst+newCoercionHole = unsafeTcPluginTcM . TcM.newCoercionHole -- | Bind an evidence variable. This must not be invoked from -- 'tcPluginInit' or 'tcPluginStop', or it will panic.
compiler/GHC/Tc/Solver.hs view
@@ -43,7 +43,7 @@ import GHC.Tc.Types.Evidence import GHC.Tc.Solver.Interact import GHC.Tc.Solver.Canonical ( makeSuperClasses, solveCallStack )-import GHC.Tc.Solver.Flatten ( flattenType )+import GHC.Tc.Solver.Rewrite ( rewriteType ) import GHC.Tc.Utils.Unify ( buildTvImplication ) import GHC.Tc.Utils.TcMType as TcM import GHC.Tc.Utils.Monad as TcM@@ -258,13 +258,13 @@ | otherwise = tyCoVarsOfCt ct `disjointVarSet` trapping_tvs float_implic :: TcTyCoVarSet -> Implication -> Maybe (Bag Ct, Bag Hole)- float_implic trapping_tvs (Implic { ic_wanted = wanted, ic_no_eqs = no_eqs+ float_implic trapping_tvs (Implic { ic_wanted = wanted, ic_given_eqs = given_eqs , ic_skols = skols, ic_status = status }) | isInsolubleStatus status = Nothing -- A short cut /plus/ we must keep track of IC_BadTelescope | otherwise = do { (simples, holes) <- float_wc new_trapping_tvs wanted- ; when (not (isEmptyBag simples) && not no_eqs) $+ ; when (not (isEmptyBag simples) && given_eqs == MaybeGivenEqs) $ Nothing -- If there are some constraints to float out, but we can't -- because we don't float out past local equalities@@ -802,7 +802,7 @@ = do { norm_loc <- getCtLocM PatCheckOrigin Nothing ; (res, _new_inerts) <- runTcSInerts inerts $ do { traceTcS "tcNormalise {" (ppr inerts)- ; ty' <- flattenType norm_loc ty+ ; ty' <- rewriteType norm_loc ty ; traceTcS "tcNormalise }" (ppr ty') ; pure ty' } ; return res }@@ -844,7 +844,7 @@ in Note [Type normalisation] in "GHC.HsToCore.Pmc". To accomplish its stated goal, tcNormalise first initialises the solver monad-with the given InertCans, then uses flattenType to simplify the desired type+with the given InertCans, then uses rewriteType to simplify the desired type with respect to the Givens in the InertCans. ***********************************************************************************@@ -938,7 +938,7 @@ ; psig_theta_vars <- mapM TcM.newEvVar psig_theta ; wanted_transformed_incl_derivs <- setTcLevel rhs_tclvl $- runTcSWithEvBinds ev_binds_var True $+ runTcSWithEvBinds ev_binds_var $ do { let loc = mkGivenLoc rhs_tclvl UnkSkol $ env_lcl tc_env psig_givens = mkGivens loc psig_theta_vars@@ -1025,13 +1025,13 @@ then return emptyBag else do implic1 <- newImplication return $ unitBag $- implic1 { ic_tclvl = rhs_tclvl- , ic_skols = qtvs- , ic_given = full_theta_vars- , ic_wanted = inner_wanted- , ic_binds = ev_binds_var- , ic_no_eqs = False- , ic_info = skol_info }+ implic1 { ic_tclvl = rhs_tclvl+ , ic_skols = qtvs+ , ic_given = full_theta_vars+ , ic_wanted = inner_wanted+ , ic_binds = ev_binds_var+ , ic_given_eqs = MaybeGivenEqs+ , ic_info = skol_info } ; return (emptyWC { wc_simple = outer_simple , wc_impl = implics })}@@ -1282,7 +1282,8 @@ mr_msg ; traceTc "decideMonoTyVars" $ vcat- [ text "mono_tvs0 =" <+> ppr mono_tvs0+ [ text "infer_mode =" <+> ppr infer_mode+ , text "mono_tvs0 =" <+> ppr mono_tvs0 , text "no_quant =" <+> ppr no_quant , text "maybe_quant =" <+> ppr maybe_quant , text "eq_constraints =" <+> ppr eq_constraints@@ -1325,7 +1326,7 @@ -- and re-simplify in case the defaulting allows further simplification defaultTyVarsAndSimplify rhs_tclvl mono_tvs candidates = do { -- Promote any tyvars that we cannot generalise- -- See Note [Promote momomorphic tyvars]+ -- See Note [Promote monomorphic tyvars] ; traceTc "decideMonoTyVars: promotion:" (ppr mono_tvs) ; any_promoted <- promoteTyVarSet mono_tvs @@ -1405,7 +1406,10 @@ dvs_plus = dv { dv_kvs = pick cand_kvs, dv_tvs = pick cand_tvs } ; traceTc "decideQuantifiedTyVars" (vcat- [ text "candidates =" <+> ppr candidates+ [ text "tau_tys =" <+> ppr tau_tys+ , text "candidates =" <+> ppr candidates+ , text "cand_kvs =" <+> ppr cand_kvs+ , text "cand_tvs =" <+> ppr cand_tvs , text "tau_tys =" <+> ppr tau_tys , text "seed_tys =" <+> ppr seed_tys , text "seed_tcvs =" <+> ppr (tyCoVarsOfTypes seed_tys)@@ -1434,7 +1438,7 @@ pred_tcvs = tyCoVarsOfType pred -{- Note [Promote momomorphic tyvars]+{- Note [Promote monomorphic tyvars] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Promote any type variables that are free in the environment. Eg f :: forall qtvs. bound_theta => zonked_tau@@ -1448,7 +1452,7 @@ so we must promote it! The inferred type is just f :: beta -> beta -NB: promoteTyVar ignores coercion variables+NB: promoteTyVarSet ignores coercion variables Note [Quantification and partial signatures] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -1641,7 +1645,7 @@ -- Solve the specified Wanted constraints -- Discard the evidence binds -- Discards all Derived stuff in result--- Postcondition: fully zonked and unflattened constraints+-- Postcondition: fully zonked simplifyWantedsTcM wanted = do { traceTc "simplifyWantedsTcM {" (ppr wanted) ; (result, _) <- runTcS (solveWantedsAndDrop (mkSimpleWC wanted))@@ -1660,22 +1664,14 @@ solveWanteds :: WantedConstraints -> TcS WantedConstraints -- so that the inert set doesn't mindlessly propagate. -- NB: wc_simples may be wanted /or/ derived now-solveWanteds wc@(WC { wc_simple = simples, wc_impl = implics, wc_holes = holes })+solveWanteds wc@(WC { wc_holes = holes }) = do { cur_lvl <- TcS.getTcLevel ; traceTcS "solveWanteds {" $ vcat [ text "Level =" <+> ppr cur_lvl , ppr wc ] - ; wc1 <- solveSimpleWanteds simples- -- Any insoluble constraints are in 'simples' and so get rewritten- -- See Note [Rewrite insolubles] in GHC.Tc.Solver.Monad-- ; (floated_eqs, implics2) <- solveNestedImplications $- implics `unionBags` wc_impl wc1-- ; dflags <- getDynFlags- ; solved_wc <- simpl_loop 0 (solverIterations dflags) floated_eqs- (wc1 { wc_impl = implics2 })+ ; dflags <- getDynFlags+ ; solved_wc <- simplify_loop 0 (solverIterations dflags) True wc ; holes' <- simplifyHoles holes ; let final_wc = solved_wc { wc_holes = holes' }@@ -1688,9 +1684,44 @@ ; return final_wc } -simpl_loop :: Int -> IntWithInf -> Cts- -> WantedConstraints -> TcS WantedConstraints-simpl_loop n limit floated_eqs wc@(WC { wc_simple = simples })+simplify_loop :: Int -> IntWithInf -> Bool+ -> WantedConstraints -> TcS WantedConstraints+-- Do a round of solving, and call maybe_simplify_again to iterate+-- The 'definitely_redo_implications' flags is False if the only reason we+-- are iterating is that we have added some new Derived superclasses (from Wanteds)+-- hoping for fundeps to help us; see Note [Superclass iteration]+--+-- Does not affect wc_holes at all; reason: wc_holes never affects anything+-- else, so we do them once, at the end in solveWanteds+simplify_loop n limit definitely_redo_implications+ wc@(WC { wc_simple = simples, wc_impl = implics })+ = do { csTraceTcS $+ text "simplify_loop iteration=" <> int n+ <+> (parens $ hsep [ text "definitely_redo =" <+> ppr definitely_redo_implications <> comma+ , int (lengthBag simples) <+> text "simples to solve" ])+ ; traceTcS "simplify_loop: wc =" (ppr wc)++ ; (unifs1, wc1) <- reportUnifications $ -- See Note [Superclass iteration]+ solveSimpleWanteds simples+ -- Any insoluble constraints are in 'simples' and so get rewritten+ -- See Note [Rewrite insolubles] in GHC.Tc.Solver.Monad++ ; wc2 <- if not definitely_redo_implications -- See Note [Superclass iteration]+ && unifs1 == 0 -- for this conditional+ && isEmptyBag (wc_impl wc1)+ then return (wc { wc_simple = wc_simple wc1 }) -- Short cut+ else do { implics2 <- solveNestedImplications $+ implics `unionBags` (wc_impl wc1)+ ; return (wc { wc_simple = wc_simple wc1+ , wc_impl = implics2 }) }++ ; unif_happened <- resetUnificationFlag+ -- Note [The Unification Level Flag] in GHC.Tc.Solver.Monad+ ; maybe_simplify_again (n+1) limit unif_happened wc2 }++maybe_simplify_again :: Int -> IntWithInf -> Bool+ -> WantedConstraints -> TcS WantedConstraints+maybe_simplify_again n limit unif_happened wc@(WC { wc_simple = simples }) | n `intGtLimit` limit = do { -- Add an error (not a warning) if we blow the limit, -- Typically if we blow the limit we are going to report some other error@@ -1699,17 +1730,12 @@ addErrTcS (hang (text "solveWanteds: too many iterations" <+> parens (text "limit =" <+> ppr limit)) 2 (vcat [ text "Unsolved:" <+> ppr wc- , ppUnless (isEmptyBag floated_eqs) $- text "Floated equalities:" <+> ppr floated_eqs , text "Set limit with -fconstraint-solver-iterations=n; n=0 for no limit" ])) ; return wc } - | not (isEmptyBag floated_eqs)- = simplify_again n limit True (wc { wc_simple = floated_eqs `unionBags` simples })- -- Put floated_eqs first so they get solved first- -- NB: the floated_eqs may include /derived/ equalities- -- arising from fundeps inside an implication+ | unif_happened+ = simplify_loop n limit True wc | superClassesMightHelp wc = -- We still have unsolved goals, and apparently no way to solve them,@@ -1722,82 +1748,65 @@ do { new_given <- makeSuperClasses pending_given ; new_wanted <- makeSuperClasses pending_wanted ; solveSimpleGivens new_given -- Add the new Givens to the inert set- ; simplify_again n limit (null pending_given)+ ; simplify_loop n limit (not (null pending_given)) $ wc { wc_simple = simples1 `unionBags` listToBag new_wanted } } }+ -- (not (null pending_given)): see Note [Superclass iteration] | otherwise = return wc -simplify_again :: Int -> IntWithInf -> Bool- -> WantedConstraints -> TcS WantedConstraints--- We have definitely decided to have another go at solving--- the wanted constraints (we have tried at least once already-simplify_again n limit no_new_given_scs- wc@(WC { wc_simple = simples, wc_impl = implics })- = do { csTraceTcS $- text "simpl_loop iteration=" <> int n- <+> (parens $ hsep [ text "no new given superclasses =" <+> ppr no_new_given_scs <> comma- , int (lengthBag simples) <+> text "simples to solve" ])- ; traceTcS "simpl_loop: wc =" (ppr wc)-- ; (unifs1, wc1) <- reportUnifications $- solveSimpleWanteds $- simples-- -- See Note [Cutting off simpl_loop]- -- We have already tried to solve the nested implications once- -- Try again only if we have unified some meta-variables- -- (which is a bit like adding more givens), or we have some- -- new Given superclasses- ; let new_implics = wc_impl wc1- ; if unifs1 == 0 &&- no_new_given_scs &&- isEmptyBag new_implics-- then -- Do not even try to solve the implications- simpl_loop (n+1) limit emptyBag (wc1 { wc_impl = implics })+{- Note [Superclass iteration]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider this implication constraint+ forall a.+ [W] d: C Int beta+ forall b. blah+where+ class D a b | a -> b+ class D a b => C a b+We will expand d's superclasses, giving [D] D Int beta, in the hope of geting+fundeps to unify beta. Doing so is usually fruitless (no useful fundeps),+and if so it seems a pity to waste time iterating the implications (forall b. blah)+(If we add new Given superclasses it's a different matter: it's really worth looking+at the implications.) - else -- Try to solve the implications- do { (floated_eqs2, implics2) <- solveNestedImplications $- implics `unionBags` new_implics- ; simpl_loop (n+1) limit floated_eqs2 (wc1 { wc_impl = implics2 })- } }+Hence the definitely_redo_implications flag to simplify_loop. It's usually+True, but False in the case where the only reason to iterate is new Derived+superclasses. In that case we check whether the new Deriveds actually led to+any new unifications, and iterate the implications only if so.+-} solveNestedImplications :: Bag Implication- -> TcS (Cts, Bag Implication)+ -> TcS (Bag Implication) -- Precondition: the TcS inerts may contain unsolved simples which have -- to be converted to givens before we go inside a nested implication. solveNestedImplications implics | isEmptyBag implics- = return (emptyBag, emptyBag)+ = return (emptyBag) | otherwise = do { traceTcS "solveNestedImplications starting {" empty- ; (floated_eqs_s, unsolved_implics) <- mapAndUnzipBagM solveImplication implics- ; let floated_eqs = concatBag floated_eqs_s+ ; unsolved_implics <- mapBagM solveImplication implics -- ... and we are back in the original TcS inerts -- Notice that the original includes the _insoluble_simples so it was safe to ignore -- them in the beginning of this function. ; traceTcS "solveNestedImplications end }" $- vcat [ text "all floated_eqs =" <+> ppr floated_eqs- , text "unsolved_implics =" <+> ppr unsolved_implics ]+ vcat [ text "unsolved_implics =" <+> ppr unsolved_implics ] - ; return (floated_eqs, catBagMaybes unsolved_implics) }+ ; return (catBagMaybes unsolved_implics) } solveImplication :: Implication -- Wanted- -> TcS (Cts, -- All wanted or derived floated equalities: var = type- Maybe Implication) -- Simplified implication (empty or singleton)+ -> TcS (Maybe Implication) -- Simplified implication (empty or singleton) -- Precondition: The TcS monad contains an empty worklist and given-only inerts -- which after trying to solve this implication we must restore to their original value solveImplication imp@(Implic { ic_tclvl = tclvl , ic_binds = ev_binds_var- , ic_skols = skols , ic_given = given_ids , ic_wanted = wanteds , ic_info = info , ic_status = status }) | isSolvedStatus status- = return (emptyCts, Just imp) -- Do nothing+ = return (Just imp) -- Do nothing | otherwise -- Even for IC_Insoluble it is worth doing more work -- The insoluble stuff might be in one sub-implication@@ -1810,7 +1819,7 @@ -- ; when debugIsOn check_tc_level -- Solve the nested constraints- ; (no_given_eqs, given_insols, residual_wanted)+ ; (has_given_eqs, given_insols, residual_wanted) <- nestImplicTcS ev_binds_var tclvl $ do { let loc = mkGivenLoc tclvl info (ic_env imp) givens = mkGivens loc given_ids@@ -1819,18 +1828,14 @@ ; residual_wanted <- solveWanteds wanteds -- solveWanteds, *not* solveWantedsAndDrop, because -- we want to retain derived equalities so we can float- -- them out in floatEqualities+ -- them out in floatEqualities. - ; (no_eqs, given_insols) <- getNoGivenEqs tclvl skols- -- Call getNoGivenEqs /after/ solveWanteds, because+ ; (has_eqs, given_insols) <- getHasGivenEqs tclvl+ -- Call getHasGivenEqs /after/ solveWanteds, because -- solveWanteds can augment the givens, via expandSuperClasses, -- to reveal given superclass equalities - ; return (no_eqs, given_insols, residual_wanted) }-- ; (floated_eqs, residual_wanted)- <- floatEqualities skols given_ids ev_binds_var- no_given_eqs residual_wanted+ ; return (has_eqs, given_insols, residual_wanted) } ; traceTcS "solveImplication 2" (ppr given_insols $$ ppr residual_wanted)@@ -1838,22 +1843,21 @@ -- Don't lose track of the insoluble givens, -- which signal unreachable code; put them in ic_wanted - ; res_implic <- setImplicationStatus (imp { ic_no_eqs = no_given_eqs+ ; res_implic <- setImplicationStatus (imp { ic_given_eqs = has_given_eqs , ic_wanted = final_wanted }) ; evbinds <- TcS.getTcEvBindsMap ev_binds_var ; tcvs <- TcS.getTcEvTyCoVars ev_binds_var ; traceTcS "solveImplication end }" $ vcat- [ text "no_given_eqs =" <+> ppr no_given_eqs- , text "floated_eqs =" <+> ppr floated_eqs+ [ text "has_given_eqs =" <+> ppr has_given_eqs , text "res_implic =" <+> ppr res_implic , text "implication evbinds =" <+> ppr (evBindMapBinds evbinds) , text "implication tvcs =" <+> ppr tcvs ] - ; return (floated_eqs, res_implic) }+ ; return res_implic } -- TcLevels must be strictly increasing (see (ImplicInv) in- -- Note [TcLevel and untouchable type variables] in GHC.Tc.Utils.TcType),+ -- Note [TcLevel invariants] in GHC.Tc.Utils.TcType), -- and in fact I think they should always increase one level at a time. -- Though sensible, this check causes lots of testsuite failures. It is@@ -2049,8 +2053,15 @@ simplifyHoles = mapBagM simpl_hole where simpl_hole :: Hole -> TcS Hole++ -- See Note [Do not simplify ConstraintHoles]+ simpl_hole h@(Hole { hole_sort = ConstraintHole }) = return h++ -- other wildcards should be simplified for printing+ -- we must do so here, and not in the error-message generation+ -- code, because we have all the givens already set up simpl_hole h@(Hole { hole_ty = ty, hole_loc = loc })- = do { ty' <- flattenType loc ty+ = do { ty' <- rewriteType loc ty ; return (h { hole_ty = ty' }) } {- Note [Delete dead Given evidence bindings]@@ -2093,6 +2104,45 @@ But we don't get to discard all redundant equality superclasses, alas; see #15205. +Note [Do not simplify ConstraintHoles]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Before printing the inferred value for a type hole (a _ wildcard in+a partial type signature), we simplify it w.r.t. any Givens. This+makes for an easier-to-understand diagnostic for the user.++However, we do not wish to do this for extra-constraint holes. Here is+the example for why (partial-sigs/should_compile/T12844):++ bar :: _ => FooData rngs+ bar = foo++ data FooData rngs++ class Foo xs where foo :: (Head xs ~ '(r,r')) => FooData xs++ type family Head (xs :: [k]) where Head (x ': xs) = x++GHC correctly infers that the extra-constraints wildcard on `bar`+should be (Head rngs ~ '(r, r'), Foo rngs). It then adds this constraint+as a Given on the implication constraint for `bar`. (This implication is+created by mkResidualConstraints in simplifyInfer.) The Hole for+the _ is stored within the implication's WantedConstraints.+When simplifyHoles is called, that constraint is already assumed as+a Given. Simplifying with respect to it turns it into+('(r, r') ~ '(r, r'), Foo rngs), which is disastrous.++Furthermore, there is no need to simplify here: extra-constraints wildcards+are filled in with the output of the solver, in chooseInferredQuantifiers+(choose_psig_context), so they are already simplified. (Contrast to normal+type holes, which are just bound to a meta-variable.) Avoiding the poor output+is simple: just don't simplify extra-constraints wildcards.++This is the only reason we need to track ConstraintHole separately+from TypeHole in HoleSort.++See also Note [Extra-constraint holes in partial type signatures]+in GHC.Tc.Gen.HsType.+ Note [Tracking redundant constraints] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ With Opt_WarnRedundantConstraints, GHC can report which@@ -2191,49 +2241,8 @@ We report (Eq a) as redundant, whereas actually (Ord a) is. But it's really not easy to detect that! --Note [Cutting off simpl_loop]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-It is very important not to iterate in simpl_loop unless there is a chance-of progress. #8474 is a classic example:-- * There's a deeply-nested chain of implication constraints.- ?x:alpha => ?y1:beta1 => ... ?yn:betan => [W] ?x:Int-- * From the innermost one we get a [D] alpha ~ Int,- but alpha is untouchable until we get out to the outermost one-- * We float [D] alpha~Int out (it is in floated_eqs), but since alpha- is untouchable, the solveInteract in simpl_loop makes no progress-- * So there is no point in attempting to re-solve- ?yn:betan => [W] ?x:Int- via solveNestedImplications, because we'll just get the- same [D] again-- * If we *do* re-solve, we'll get an infinite loop. It is cut off by- the fixed bound of 10, but solving the next takes 10*10*...*10 (ie- exponentially many) iterations!--Conclusion: we should call solveNestedImplications only if we did-some unification in solveSimpleWanteds; because that's the only way-we'll get more Givens (a unification is like adding a Given) to-allow the implication to make progress. -} -promoteTyVarTcS :: TcTyVar -> TcS ()--- When we float a constraint out of an implication we must restore--- invariant (WantedInv) in Note [TcLevel and untouchable type variables] in GHC.Tc.Utils.TcType--- See Note [Promoting unification variables]--- We don't just call promoteTyVar because we want to use unifyTyVar,--- not writeMetaTyVar-promoteTyVarTcS tv- = do { tclvl <- TcS.getTcLevel- ; when (isFloatedTouchableMetaTyVar tclvl tv) $- do { cloned_tv <- TcS.cloneMetaTyVar tv- ; let rhs_tv = setMetaTyVarTcLevel cloned_tv tclvl- ; unifyTyVar tv (mkTyVarTy rhs_tv) } }- -- | Like 'defaultTyVar', but in the TcS monad. defaultTyVarTcS :: TcTyVar -> TcS Bool defaultTyVarTcS the_tv@@ -2268,7 +2277,7 @@ concatMapBag (float_implic trapping_tvs) implics float_implic :: TcTyCoVarSet -> Implication -> Cts float_implic trapping_tvs imp- | float_past_equalities || ic_no_eqs imp+ | float_past_equalities || ic_given_eqs imp /= MaybeGivenEqs = float_wc new_trapping_tvs (ic_wanted imp) | otherwise -- Take care with equalities = emptyCts -- See (1) under Note [ApproximateWC]@@ -2368,7 +2377,7 @@ a) Promote any meta-tyvars that have been floated out by approximateWC, to restore invariant (WantedInv) described in- Note [TcLevel and untouchable type variables] in GHC.Tc.Utils.TcType.+ Note [TcLevel invariants] in GHC.Tc.Utils.TcType. b) Default the kind of any meta-tyvars that are not mentioned in in the environment.@@ -2384,8 +2393,7 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When we float an equality out of an implication we must "promote" free unification variables of the equality, in order to maintain Invariant-(WantedInv) from Note [TcLevel and untouchable type variables] in-TcType. for the leftover implication.+(WantedInv) from Note [TcLevel invariants] in GHC.Tc.Types.TcType. This is absolutely necessary. Consider the following example. We start with two implications and a class with a functional dependency.@@ -2420,276 +2428,6 @@ g1 _ = h [x] g2 z = case z of TEx y -> (h [[undefined]], op x [y]) in (g1 '3', g2 undefined)----*********************************************************************************-* *-* Floating equalities *-* *-*********************************************************************************--Note [Float Equalities out of Implications]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-For ordinary pattern matches (including existentials) we float-equalities out of implications, for instance:- data T where- MkT :: Eq a => a -> T- f x y = case x of MkT _ -> (y::Int)-We get the implication constraint (x::T) (y::alpha):- forall a. [untouchable=alpha] Eq a => alpha ~ Int-We want to float out the equality into a scope where alpha is no-longer untouchable, to solve the implication!--But we cannot float equalities out of implications whose givens may-yield or contain equalities:-- data T a where- T1 :: T Int- T2 :: T Bool- T3 :: T a-- h :: T a -> a -> Int-- f x y = case x of- T1 -> y::Int- T2 -> y::Bool- T3 -> h x y--We generate constraint, for (x::T alpha) and (y :: beta):- [untouchables = beta] (alpha ~ Int => beta ~ Int) -- From 1st branch- [untouchables = beta] (alpha ~ Bool => beta ~ Bool) -- From 2nd branch- (alpha ~ beta) -- From 3rd branch--If we float the equality (beta ~ Int) outside of the first implication and-the equality (beta ~ Bool) out of the second we get an insoluble constraint.-But if we just leave them inside the implications, we unify alpha := beta and-solve everything.--Principle:- We do not want to float equalities out which may- need the given *evidence* to become soluble.--Consequence: classes with functional dependencies don't matter (since there is-no evidence for a fundep equality), but equality superclasses do matter (since-they carry evidence).--}--floatEqualities :: [TcTyVar] -> [EvId] -> EvBindsVar -> Bool- -> WantedConstraints- -> TcS (Cts, WantedConstraints)--- Main idea: see Note [Float Equalities out of Implications]------ Precondition: the wc_simple of the incoming WantedConstraints are--- fully zonked, so that we can see their free variables------ Postcondition: The returned floated constraints (Cts) are only--- Wanted or Derived------ Also performs some unifications (via promoteTyVar), adding to--- monadically-carried ty_binds. These will be used when processing--- floated_eqs later------ Subtleties: Note [Float equalities from under a skolem binding]--- Note [Skolem escape]--- Note [What prevents a constraint from floating]-floatEqualities skols given_ids ev_binds_var no_given_eqs- wanteds@(WC { wc_simple = simples })- | not no_given_eqs -- There are some given equalities, so don't float- = return (emptyBag, wanteds) -- Note [Float Equalities out of Implications]-- | otherwise- = do { -- First zonk: the inert set (from whence they came) is fully- -- zonked, but unflattening may have filled in unification- -- variables, and we /must/ see them. Otherwise we may float- -- constraints that mention the skolems!- simples <- TcS.zonkSimples simples- ; binds <- TcS.getTcEvBindsMap ev_binds_var-- -- Now we can pick the ones to float- -- The constraints are un-flattened and de-canonicalised- ; let (candidate_eqs, no_float_cts) = partitionBag is_float_eq_candidate simples-- seed_skols = mkVarSet skols `unionVarSet`- mkVarSet given_ids `unionVarSet`- foldr add_non_flt_ct emptyVarSet no_float_cts `unionVarSet`- evBindMapToVarSet binds- -- seed_skols: See Note [What prevents a constraint from floating] (1,2,3)- -- Include the EvIds of any non-floating constraints-- extended_skols = transCloVarSet (add_captured_ev_ids candidate_eqs) seed_skols- -- extended_skols contains the EvIds of all the trapped constraints- -- See Note [What prevents a constraint from floating] (3)-- (flt_eqs, no_flt_eqs) = partitionBag (is_floatable extended_skols)- candidate_eqs-- remaining_simples = no_float_cts `andCts` no_flt_eqs-- -- Promote any unification variables mentioned in the floated equalities- -- See Note [Promoting unification variables]- ; mapM_ promoteTyVarTcS (tyCoVarsOfCtsList flt_eqs)-- ; traceTcS "floatEqualities" (vcat [ text "Skols =" <+> ppr skols- , text "Extended skols =" <+> ppr extended_skols- , text "Simples =" <+> ppr simples- , text "Candidate eqs =" <+> ppr candidate_eqs- , text "Floated eqs =" <+> ppr flt_eqs])- ; return ( flt_eqs, wanteds { wc_simple = remaining_simples } ) }-- where- add_non_flt_ct :: Ct -> VarSet -> VarSet- add_non_flt_ct ct acc | isDerivedCt ct = acc- | otherwise = extendVarSet acc (ctEvId ct)-- is_floatable :: VarSet -> Ct -> Bool- is_floatable skols ct- | isDerivedCt ct = tyCoVarsOfCt ct `disjointVarSet` skols- | otherwise = not (ctEvId ct `elemVarSet` skols)-- add_captured_ev_ids :: Cts -> VarSet -> VarSet- add_captured_ev_ids cts skols = foldr extra_skol emptyVarSet cts- where- extra_skol ct acc- | isDerivedCt ct = acc- | tyCoVarsOfCt ct `intersectsVarSet` skols = extendVarSet acc (ctEvId ct)- | otherwise = acc-- -- Identify which equalities are candidates for floating- -- Float out alpha ~ ty which might be unified outside- -- See Note [Which equalities to float]- is_float_eq_candidate ct- | pred <- ctPred ct- , EqPred NomEq ty1 ty2 <- classifyPredType pred- , case ct of- CIrredCan {} -> False -- See Note [Do not float blocked constraints]- _ -> True -- See #18855- = float_eq ty1 ty2 || float_eq ty2 ty1- | otherwise- = False-- float_eq ty1 ty2- = case getTyVar_maybe ty1 of- Just tv1 -> isMetaTyVar tv1- && (not (isTyVarTyVar tv1) || isTyVarTy ty2)- Nothing -> False--{- Note [Do not float blocked constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-As #18855 showed, we must not float an equality that is blocked.-Consider- forall a[4]. [W] co1: alpha[4] ~ Maybe (a[4] |> bco)- [W] co2: alpha[4] ~ Maybe (beta[4] |> bco])- [W] bco: kappa[2] ~ Type--Now co1, co2 are blocked by bco. We will eventually float out bco-and solve it at level 2. But the danger is that we will *also*-float out co2, and that is bad bad bad. Because we'll promote alpha-and beta to level 2, and then fail to unify the promoted beta-with the skolem a[4].--Solution: don't float out blocked equalities. Remember: we only want-to float out if we can solve; see Note [Which equalities to float].--(Future plan: kill floating altogether.)--Note [Float equalities from under a skolem binding]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Which of the simple equalities can we float out? Obviously, only-ones that don't mention the skolem-bound variables. But that is-over-eager. Consider- [2] forall a. F a beta[1] ~ gamma[2], G beta[1] gamma[2] ~ Int-The second constraint doesn't mention 'a'. But if we float it,-we'll promote gamma[2] to gamma'[1]. Now suppose that we learn that-beta := Bool, and F a Bool = a, and G Bool _ = Int. Then we'll-we left with the constraint- [2] forall a. a ~ gamma'[1]-which is insoluble because gamma became untouchable.--Solution: float only constraints that stand a jolly good chance of-being soluble simply by being floated, namely ones of form- a ~ ty-where 'a' is a currently-untouchable unification variable, but may-become touchable by being floated (perhaps by more than one level).--We had a very complicated rule previously, but this is nice and-simple. (To see the notes, look at this Note in a version of-GHC.Tc.Solver prior to Oct 2014).--Note [Which equalities to float]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Which equalities should we float? We want to float ones where there-is a decent chance that floating outwards will allow unification to-happen. In particular, float out equalities that are:--* Of form (alpha ~# ty) or (ty ~# alpha), where- * alpha is a meta-tyvar.- * And 'alpha' is not a TyVarTv with 'ty' being a non-tyvar. In that- case, floating out won't help either, and it may affect grouping- of error messages.-- NB: generally we won't see (ty ~ alpha), with alpha on the right because- of Note [Unification variables on the left] in GHC.Tc.Utils.Unify.- But if we start with (F tys ~ alpha), it will orient as (fmv ~ alpha),- and unflatten back to (F tys ~ alpha). So we must look for alpha on- the right too. Example T4494.--* Nominal. No point in floating (alpha ~R# ty), because we do not- unify representational equalities even if alpha is touchable.- See Note [Do not unify representational equalities] in GHC.Tc.Solver.Interact.--Note [Skolem escape]-~~~~~~~~~~~~~~~~~~~~-You might worry about skolem escape with all this floating.-For example, consider- [2] forall a. (a ~ F beta[2] delta,- Maybe beta[2] ~ gamma[1])--The (Maybe beta ~ gamma) doesn't mention 'a', so we float it, and-solve with gamma := beta. But what if later delta:=Int, and- F b Int = b.-Then we'd get a ~ beta[2], and solve to get beta:=a, and now the-skolem has escaped!--But it's ok: when we float (Maybe beta[2] ~ gamma[1]), we promote beta[2]-to beta[1], and that means the (a ~ beta[1]) will be stuck, as it should be.--Note [What prevents a constraint from floating]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-What /prevents/ a constraint from floating? If it mentions one of the-"bound variables of the implication". What are they?--The "bound variables of the implication" are-- 1. The skolem type variables `ic_skols`-- 2. The "given" evidence variables `ic_given`. Example:- forall a. (co :: t1 ~# t2) => [W] co2 : (a ~# b |> co)- Here 'co' is bound-- 3. The binders of all evidence bindings in `ic_binds`. Example- forall a. (d :: t1 ~ t2)- EvBinds { (co :: t1 ~# t2) = superclass-sel d }- => [W] co2 : (a ~# b |> co)- Here `co` is gotten by superclass selection from `d`, and the- wanted constraint co2 must not float.-- 4. And the evidence variable of any equality constraint (incl- Wanted ones) whose type mentions a bound variable. Example:- forall k. [W] co1 :: t1 ~# t2 |> co2- [W] co2 :: k ~# *- Here, since `k` is bound, so is `co2` and hence so is `co1`.--Here (1,2,3) are handled by the "seed_skols" calculation, and-(4) is done by the transCloVarSet call.--The possible dependence on givens, and evidence bindings, is more-subtle than we'd realised at first. See #14584.--How can (4) arise? Suppose we have (k :: *), (a :: k), and ([G} k ~ *).-Then form an equality like (a ~ Int) we might end up with- [W] co1 :: k ~ *- [W] co2 :: (a |> co1) ~ Int *********************************************************************************
compiler/GHC/Tc/Solver/Canonical.hs view
@@ -1,2625 +1,3216 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFunctor #-}--module GHC.Tc.Solver.Canonical(- canonicalize,- unifyDerived,- makeSuperClasses, maybeSym,- StopOrContinue(..), stopWith, continueWith,- solveCallStack -- For GHC.Tc.Solver- ) where--#include "GhclibHsVersions.h"--import GHC.Prelude--import GHC.Tc.Types.Constraint-import GHC.Core.Predicate-import GHC.Tc.Types.Origin-import GHC.Tc.Utils.Unify( swapOverTyVars, metaTyVarUpdateOK, MetaTyVarUpdateResult(..) )-import GHC.Tc.Utils.TcType-import GHC.Core.Type-import GHC.Tc.Solver.Flatten-import GHC.Tc.Solver.Monad-import GHC.Tc.Types.Evidence-import GHC.Tc.Types.EvTerm-import GHC.Core.Class-import GHC.Core.TyCon-import GHC.Core.Multiplicity-import GHC.Core.TyCo.Rep -- cleverly decomposes types, good for completeness checking-import GHC.Core.Coercion-import GHC.Core-import GHC.Types.Id( mkTemplateLocals )-import GHC.Core.FamInstEnv ( FamInstEnvs )-import GHC.Tc.Instance.Family ( tcTopNormaliseNewTypeTF_maybe )-import GHC.Types.Var-import GHC.Types.Var.Env( mkInScopeSet )-import GHC.Types.Var.Set( delVarSetList )-import GHC.Utils.Outputable-import GHC.Utils.Panic-import GHC.Driver.Session( DynFlags )-import GHC.Types.Name.Set-import GHC.Types.Name.Reader-import GHC.Hs.Type( HsIPName(..) )--import GHC.Data.Pair-import GHC.Utils.Misc-import GHC.Data.Bag-import GHC.Utils.Monad-import Control.Monad-import Data.Maybe ( isJust )-import Data.List ( zip4 )-import GHC.Types.Basic--import Data.Bifunctor ( bimap )-import Data.Foldable ( traverse_ )--{--************************************************************************-* *-* The Canonicaliser *-* *-************************************************************************--Note [Canonicalization]-~~~~~~~~~~~~~~~~~~~~~~~--Canonicalization converts a simple constraint to a canonical form. It is-unary (i.e. treats individual constraints one at a time).--Constraints originating from user-written code come into being as-CNonCanonicals. We know nothing about these constraints. So, first:-- Classify CNonCanoncal constraints, depending on whether they- are equalities, class predicates, or other.--Then proceed depending on the shape of the constraint. Generally speaking,-each constraint gets flattened and then decomposed into one of several forms-(see type Ct in GHC.Tc.Types).--When an already-canonicalized constraint gets kicked out of the inert set,-it must be recanonicalized. But we know a bit about its shape from the-last time through, so we can skip the classification step.---}---- Top-level canonicalization--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--canonicalize :: Ct -> TcS (StopOrContinue Ct)-canonicalize (CNonCanonical { cc_ev = ev })- = {-# SCC "canNC" #-}- case classifyPredType pred of- ClassPred cls tys -> do traceTcS "canEvNC:cls" (ppr cls <+> ppr tys)- canClassNC ev cls tys- EqPred eq_rel ty1 ty2 -> do traceTcS "canEvNC:eq" (ppr ty1 $$ ppr ty2)- canEqNC ev eq_rel ty1 ty2- IrredPred {} -> do traceTcS "canEvNC:irred" (ppr pred)- canIrred OtherCIS ev- ForAllPred tvs th p -> do traceTcS "canEvNC:forall" (ppr pred)- canForAllNC ev tvs th p- where- pred = ctEvPred ev--canonicalize (CQuantCan (QCI { qci_ev = ev, qci_pend_sc = pend_sc }))- = canForAll ev pend_sc--canonicalize (CIrredCan { cc_ev = ev, cc_status = status })- | EqPred eq_rel ty1 ty2 <- classifyPredType (ctEvPred ev)- = -- For insolubles (all of which are equalities, do /not/ flatten the arguments- -- In #14350 doing so led entire-unnecessary and ridiculously large- -- type function expansion. Instead, canEqNC just applies- -- the substitution to the predicate, and may do decomposition;- -- e.g. a ~ [a], where [G] a ~ [Int], can decompose- canEqNC ev eq_rel ty1 ty2-- | otherwise- = canIrred status ev--canonicalize (CDictCan { cc_ev = ev, cc_class = cls- , cc_tyargs = xis, cc_pend_sc = pend_sc })- = {-# SCC "canClass" #-}- canClass ev cls xis pend_sc--canonicalize (CTyEqCan { cc_ev = ev- , cc_tyvar = tv- , cc_rhs = xi- , cc_eq_rel = eq_rel })- = {-# SCC "canEqLeafTyVarEq" #-}- canEqNC ev eq_rel (mkTyVarTy tv) xi- -- NB: Don't use canEqTyVar because that expects flattened types,- -- and tv and xi may not be flat w.r.t. an updated inert set--canonicalize (CFunEqCan { cc_ev = ev- , cc_fun = fn- , cc_tyargs = xis1- , cc_fsk = fsk })- = {-# SCC "canEqLeafFunEq" #-}- canCFunEqCan ev fn xis1 fsk--{--************************************************************************-* *-* Class Canonicalization-* *-************************************************************************--}--canClassNC :: CtEvidence -> Class -> [Type] -> TcS (StopOrContinue Ct)--- "NC" means "non-canonical"; that is, we have got here--- from a NonCanonical constraint, not from a CDictCan--- Precondition: EvVar is class evidence-canClassNC ev cls tys- | isGiven ev -- See Note [Eagerly expand given superclasses]- = do { sc_cts <- mkStrictSuperClasses ev [] [] cls tys- ; emitWork sc_cts- ; canClass ev cls tys False }-- | isWanted ev- , Just ip_name <- isCallStackPred cls tys- , OccurrenceOf func <- ctLocOrigin loc- -- If we're given a CallStack constraint that arose from a function- -- call, we need to push the current call-site onto the stack instead- -- of solving it directly from a given.- -- See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence- -- and Note [Solving CallStack constraints] in GHC.Tc.Solver.Monad- = do { -- First we emit a new constraint that will capture the- -- given CallStack.- ; let new_loc = setCtLocOrigin loc (IPOccOrigin (HsIPName ip_name))- -- We change the origin to IPOccOrigin so- -- this rule does not fire again.- -- See Note [Overview of implicit CallStacks]-- ; new_ev <- newWantedEvVarNC new_loc pred-- -- Then we solve the wanted by pushing the call-site- -- onto the newly emitted CallStack- ; let ev_cs = EvCsPushCall func (ctLocSpan loc) (ctEvExpr new_ev)- ; solveCallStack ev ev_cs-- ; canClass new_ev cls tys False }-- | otherwise- = canClass ev cls tys (has_scs cls)-- where- has_scs cls = not (null (classSCTheta cls))- loc = ctEvLoc ev- pred = ctEvPred ev--solveCallStack :: CtEvidence -> EvCallStack -> TcS ()--- Also called from GHC.Tc.Solver when defaulting call stacks-solveCallStack ev ev_cs = do- -- We're given ev_cs :: CallStack, but the evidence term should be a- -- dictionary, so we have to coerce ev_cs to a dictionary for- -- `IP ip CallStack`. See Note [Overview of implicit CallStacks]- cs_tm <- evCallStack ev_cs- let ev_tm = mkEvCast cs_tm (wrapIP (ctEvPred ev))- setEvBindIfWanted ev ev_tm--canClass :: CtEvidence- -> Class -> [Type]- -> Bool -- True <=> un-explored superclasses- -> TcS (StopOrContinue Ct)--- Precondition: EvVar is class evidence--canClass ev cls tys pend_sc- = -- all classes do *nominal* matching- ASSERT2( ctEvRole ev == Nominal, ppr ev $$ ppr cls $$ ppr tys )- do { (xis, cos, _kind_co) <- flattenArgsNom ev cls_tc tys- ; MASSERT( isTcReflCo _kind_co )- ; let co = mkTcTyConAppCo Nominal cls_tc cos- xi = mkClassPred cls xis- mk_ct new_ev = CDictCan { cc_ev = new_ev- , cc_tyargs = xis- , cc_class = cls- , cc_pend_sc = pend_sc }- ; mb <- rewriteEvidence ev xi co- ; traceTcS "canClass" (vcat [ ppr ev- , ppr xi, ppr mb ])- ; return (fmap mk_ct mb) }- where- cls_tc = classTyCon cls--{- Note [The superclass story]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We need to add superclass constraints for two reasons:--* For givens [G], they give us a route to proof. E.g.- f :: Ord a => a -> Bool- f x = x == x- We get a Wanted (Eq a), which can only be solved from the superclass- of the Given (Ord a).--* For wanteds [W], and deriveds [WD], [D], they may give useful- functional dependencies. E.g.- class C a b | a -> b where ...- class C a b => D a b where ...- Now a [W] constraint (D Int beta) has (C Int beta) as a superclass- and that might tell us about beta, via C's fundeps. We can get this- by generating a [D] (C Int beta) constraint. It's derived because- we don't actually have to cough up any evidence for it; it's only there- to generate fundep equalities.--See Note [Why adding superclasses can help].--For these reasons we want to generate superclass constraints for both-Givens and Wanteds. But:--* (Minor) they are often not needed, so generating them aggressively- is a waste of time.--* (Major) if we want recursive superclasses, there would be an infinite- number of them. Here is a real-life example (#10318);-- class (Frac (Frac a) ~ Frac a,- Fractional (Frac a),- IntegralDomain (Frac a))- => IntegralDomain a where- type Frac a :: *-- Notice that IntegralDomain has an associated type Frac, and one- of IntegralDomain's superclasses is another IntegralDomain constraint.--So here's the plan:--1. Eagerly generate superclasses for given (but not wanted)- constraints; see Note [Eagerly expand given superclasses].- This is done using mkStrictSuperClasses in canClassNC, when- we take a non-canonical Given constraint and cannonicalise it.-- However stop if you encounter the same class twice. That is,- mkStrictSuperClasses expands eagerly, but has a conservative- termination condition: see Note [Expanding superclasses] in GHC.Tc.Utils.TcType.--2. Solve the wanteds as usual, but do no further expansion of- superclasses for canonical CDictCans in solveSimpleGivens or- solveSimpleWanteds; Note [Danger of adding superclasses during solving]-- However, /do/ continue to eagerly expand superclasses for new /given/- /non-canonical/ constraints (canClassNC does this). As #12175- showed, a type-family application can expand to a class constraint,- and we want to see its superclasses for just the same reason as- Note [Eagerly expand given superclasses].--3. If we have any remaining unsolved wanteds- (see Note [When superclasses help] in GHC.Tc.Types.Constraint)- try harder: take both the Givens and Wanteds, and expand- superclasses again. See the calls to expandSuperClasses in- GHC.Tc.Solver.simpl_loop and solveWanteds.-- This may succeed in generating (a finite number of) extra Givens,- and extra Deriveds. Both may help the proof.--3a An important wrinkle: only expand Givens from the current level.- Two reasons:- - We only want to expand it once, and that is best done at- the level it is bound, rather than repeatedly at the leaves- of the implication tree- - We may be inside a type where we can't create term-level- evidence anyway, so we can't superclass-expand, say,- (a ~ b) to get (a ~# b). This happened in #15290.--4. Go round to (2) again. This loop (2,3,4) is implemented- in GHC.Tc.Solver.simpl_loop.--The cc_pend_sc flag in a CDictCan records whether the superclasses of-this constraint have been expanded. Specifically, in Step 3 we only-expand superclasses for constraints with cc_pend_sc set to true (i.e.-isPendingScDict holds).--Why do we do this? Two reasons:--* To avoid repeated work, by repeatedly expanding the superclasses of- same constraint,--* To terminate the above loop, at least in the -XNoRecursiveSuperClasses- case. If there are recursive superclasses we could, in principle,- expand forever, always encountering new constraints.--When we take a CNonCanonical or CIrredCan, but end up classifying it-as a CDictCan, we set the cc_pend_sc flag to False.--Note [Superclass loops]-~~~~~~~~~~~~~~~~~~~~~~~-Suppose we have- class C a => D a- class D a => C a--Then, when we expand superclasses, we'll get back to the self-same-predicate, so we have reached a fixpoint in expansion and there is no-point in fruitlessly expanding further. This case just falls out from-our strategy. Consider- f :: C a => a -> Bool- f x = x==x-Then canClassNC gets the [G] d1: C a constraint, and eager emits superclasses-G] d2: D a, [G] d3: C a (psc). (The "psc" means it has its sc_pend flag set.)-When processing d3 we find a match with d1 in the inert set, and we always-keep the inert item (d1) if possible: see Note [Replacement vs keeping] in-GHC.Tc.Solver.Interact. So d3 dies a quick, happy death.--Note [Eagerly expand given superclasses]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-In step (1) of Note [The superclass story], why do we eagerly expand-Given superclasses by one layer? (By "one layer" we mean expand transitively-until you meet the same class again -- the conservative criterion embodied-in expandSuperClasses. So a "layer" might be a whole stack of superclasses.)-We do this eagerly for Givens mainly because of some very obscure-cases like this:-- instance Bad a => Eq (T a)-- f :: (Ord (T a)) => blah- f x = ....needs Eq (T a), Ord (T a)....--Here if we can't satisfy (Eq (T a)) from the givens we'll use the-instance declaration; but then we are stuck with (Bad a). Sigh.-This is really a case of non-confluent proofs, but to stop our users-complaining we expand one layer in advance.--Note [Instance and Given overlap] in GHC.Tc.Solver.Interact.--We also want to do this if we have-- f :: F (T a) => blah--where- type instance F (T a) = Ord (T a)--So we may need to do a little work on the givens to expose the-class that has the superclasses. That's why the superclass-expansion for Givens happens in canClassNC.--This same scenario happens with quantified constraints, whose superclasses-are also eagerly expanded. Test case: typecheck/should_compile/T16502b-These are handled in canForAllNC, analogously to canClassNC.--Note [Why adding superclasses can help]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Examples of how adding superclasses can help:-- --- Example 1- class C a b | a -> b- Suppose we want to solve- [G] C a b- [W] C a beta- Then adding [D] beta~b will let us solve it.-- -- Example 2 (similar but using a type-equality superclass)- class (F a ~ b) => C a b- And try to sllve:- [G] C a b- [W] C a beta- Follow the superclass rules to add- [G] F a ~ b- [D] F a ~ beta- Now we get [D] beta ~ b, and can solve that.-- -- Example (tcfail138)- class L a b | a -> b- class (G a, L a b) => C a b-- instance C a b' => G (Maybe a)- instance C a b => C (Maybe a) a- instance L (Maybe a) a-- When solving the superclasses of the (C (Maybe a) a) instance, we get- [G] C a b, and hance by superclasses, [G] G a, [G] L a b- [W] G (Maybe a)- Use the instance decl to get- [W] C a beta- Generate its derived superclass- [D] L a beta. Now using fundeps, combine with [G] L a b to get- [D] beta ~ b- which is what we want.--Note [Danger of adding superclasses during solving]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Here's a serious, but now out-dated example, from #4497:-- class Num (RealOf t) => Normed t- type family RealOf x--Assume the generated wanted constraint is:- [W] RealOf e ~ e- [W] Normed e--If we were to be adding the superclasses during simplification we'd get:- [W] RealOf e ~ e- [W] Normed e- [D] RealOf e ~ fuv- [D] Num fuv-==>- e := fuv, Num fuv, Normed fuv, RealOf fuv ~ fuv--While looks exactly like our original constraint. If we add the-superclass of (Normed fuv) again we'd loop. By adding superclasses-definitely only once, during canonicalisation, this situation can't-happen.--Mind you, now that Wanteds cannot rewrite Derived, I think this particular-situation can't happen.--Note [Nested quantified constraint superclasses]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider (typecheck/should_compile/T17202)-- class C1 a- class (forall c. C1 c) => C2 a- class (forall b. (b ~ F a) => C2 a) => C3 a--Elsewhere in the code, we get a [G] g1 :: C3 a. We expand its superclass-to get [G] g2 :: (forall b. (b ~ F a) => C2 a). This constraint has a-superclass, as well. But we now must be careful: we cannot just add-(forall c. C1 c) as a Given, because we need to remember g2's context.-That new constraint is Given only when forall b. (b ~ F a) is true.--It's tempting to make the new Given be (forall b. (b ~ F a) => forall c. C1 c),-but that's problematic, because it's nested, and ForAllPred is not capable-of representing a nested quantified constraint. (We could change ForAllPred-to allow this, but the solution in this Note is much more local and simpler.)--So, we swizzle it around to get (forall b c. (b ~ F a) => C1 c).--More generally, if we are expanding the superclasses of- g0 :: forall tvs. theta => cls tys-and find a superclass constraint- forall sc_tvs. sc_theta => sc_inner_pred-we must have a selector- sel_id :: forall cls_tvs. cls cls_tvs -> forall sc_tvs. sc_theta => sc_inner_pred-and thus build- g_sc :: forall tvs sc_tvs. theta => sc_theta => sc_inner_pred- g_sc = /\ tvs. /\ sc_tvs. \ theta_ids. \ sc_theta_ids.- sel_id tys (g0 tvs theta_ids) sc_tvs sc_theta_ids--Actually, we cheat a bit by eta-reducing: note that sc_theta_ids are both the-last bound variables and the last arguments. This avoids the need to produce-the sc_theta_ids at all. So our final construction is-- g_sc = /\ tvs. /\ sc_tvs. \ theta_ids.- sel_id tys (g0 tvs theta_ids) sc_tvs-- -}--makeSuperClasses :: [Ct] -> TcS [Ct]--- Returns strict superclasses, transitively, see Note [The superclasses story]--- See Note [The superclass story]--- The loop-breaking here follows Note [Expanding superclasses] in GHC.Tc.Utils.TcType--- Specifically, for an incoming (C t) constraint, we return all of (C t)'s--- superclasses, up to /and including/ the first repetition of C------ Example: class D a => C a--- class C [a] => D a--- makeSuperClasses (C x) will return (D x, C [x])------ NB: the incoming constraints have had their cc_pend_sc flag already--- flipped to False, by isPendingScDict, so we are /obliged/ to at--- least produce the immediate superclasses-makeSuperClasses cts = concatMapM go cts- where- go (CDictCan { cc_ev = ev, cc_class = cls, cc_tyargs = tys })- = mkStrictSuperClasses ev [] [] cls tys- go (CQuantCan (QCI { qci_pred = pred, qci_ev = ev }))- = ASSERT2( isClassPred pred, ppr pred ) -- The cts should all have- -- class pred heads- mkStrictSuperClasses ev tvs theta cls tys- where- (tvs, theta, cls, tys) = tcSplitDFunTy (ctEvPred ev)- go ct = pprPanic "makeSuperClasses" (ppr ct)--mkStrictSuperClasses- :: CtEvidence- -> [TyVar] -> ThetaType -- These two args are non-empty only when taking- -- superclasses of a /quantified/ constraint- -> Class -> [Type] -> TcS [Ct]--- Return constraints for the strict superclasses of--- ev :: forall as. theta => cls tys-mkStrictSuperClasses ev tvs theta cls tys- = mk_strict_superclasses (unitNameSet (className cls))- ev tvs theta cls tys--mk_strict_superclasses :: NameSet -> CtEvidence- -> [TyVar] -> ThetaType- -> Class -> [Type] -> TcS [Ct]--- Always return the immediate superclasses of (cls tys);--- and expand their superclasses, provided none of them are in rec_clss--- nor are repeated-mk_strict_superclasses rec_clss (CtGiven { ctev_evar = evar, ctev_loc = loc })- tvs theta cls tys- = concatMapM (do_one_given (mk_given_loc loc)) $- classSCSelIds cls- where- dict_ids = mkTemplateLocals theta- size = sizeTypes tys-- do_one_given given_loc sel_id- | isUnliftedType sc_pred- , not (null tvs && null theta)- = -- See Note [Equality superclasses in quantified constraints]- return []- | otherwise- = do { given_ev <- newGivenEvVar given_loc $- mk_given_desc sel_id sc_pred- ; mk_superclasses rec_clss given_ev tvs theta sc_pred }- where- sc_pred = classMethodInstTy sel_id tys-- -- See Note [Nested quantified constraint superclasses]- mk_given_desc :: Id -> PredType -> (PredType, EvTerm)- mk_given_desc sel_id sc_pred- = (swizzled_pred, swizzled_evterm)- where- (sc_tvs, sc_rho) = splitForAllTyCoVars sc_pred- (sc_theta, sc_inner_pred) = splitFunTys sc_rho-- all_tvs = tvs `chkAppend` sc_tvs- all_theta = theta `chkAppend` (map scaledThing sc_theta)- swizzled_pred = mkInfSigmaTy all_tvs all_theta sc_inner_pred-- -- evar :: forall tvs. theta => cls tys- -- sel_id :: forall cls_tvs. cls cls_tvs- -- -> forall sc_tvs. sc_theta => sc_inner_pred- -- swizzled_evterm :: forall tvs sc_tvs. theta => sc_theta => sc_inner_pred- swizzled_evterm = EvExpr $- mkLams all_tvs $- mkLams dict_ids $- Var sel_id- `mkTyApps` tys- `App` (evId evar `mkVarApps` (tvs ++ dict_ids))- `mkVarApps` sc_tvs-- mk_given_loc loc- | isCTupleClass cls- = loc -- For tuple predicates, just take them apart, without- -- adding their (large) size into the chain. When we- -- get down to a base predicate, we'll include its size.- -- #10335-- | GivenOrigin skol_info <- ctLocOrigin loc- -- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance- -- for explantation of this transformation for givens- = case skol_info of- InstSkol -> loc { ctl_origin = GivenOrigin (InstSC size) }- InstSC n -> loc { ctl_origin = GivenOrigin (InstSC (n `max` size)) }- _ -> loc-- | otherwise -- Probably doesn't happen, since this function- = loc -- is only used for Givens, but does no harm--mk_strict_superclasses rec_clss ev tvs theta cls tys- | all noFreeVarsOfType tys- = return [] -- Wanteds with no variables yield no deriveds.- -- See Note [Improvement from Ground Wanteds]-- | otherwise -- Wanted/Derived case, just add Derived superclasses- -- that can lead to improvement.- = ASSERT2( null tvs && null theta, ppr tvs $$ ppr theta )- concatMapM do_one_derived (immSuperClasses cls tys)- where- loc = ctEvLoc ev-- do_one_derived sc_pred- = do { sc_ev <- newDerivedNC loc sc_pred- ; mk_superclasses rec_clss sc_ev [] [] sc_pred }--{- Note [Improvement from Ground Wanteds]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose class C b a => D a b-and consider- [W] D Int Bool-Is there any point in emitting [D] C Bool Int? No! The only point of-emitting superclass constraints for W/D constraints is to get-improvement, extra unifications that result from functional-dependencies. See Note [Why adding superclasses can help] above.--But no variables means no improvement; case closed.--}--mk_superclasses :: NameSet -> CtEvidence- -> [TyVar] -> ThetaType -> PredType -> TcS [Ct]--- Return this constraint, plus its superclasses, if any-mk_superclasses rec_clss ev tvs theta pred- | ClassPred cls tys <- classifyPredType pred- = mk_superclasses_of rec_clss ev tvs theta cls tys-- | otherwise -- Superclass is not a class predicate- = return [mkNonCanonical ev]--mk_superclasses_of :: NameSet -> CtEvidence- -> [TyVar] -> ThetaType -> Class -> [Type]- -> TcS [Ct]--- Always return this class constraint,--- and expand its superclasses-mk_superclasses_of rec_clss ev tvs theta cls tys- | loop_found = do { traceTcS "mk_superclasses_of: loop" (ppr cls <+> ppr tys)- ; return [this_ct] } -- cc_pend_sc of this_ct = True- | otherwise = do { traceTcS "mk_superclasses_of" (vcat [ ppr cls <+> ppr tys- , ppr (isCTupleClass cls)- , ppr rec_clss- ])- ; sc_cts <- mk_strict_superclasses rec_clss' ev tvs theta cls tys- ; return (this_ct : sc_cts) }- -- cc_pend_sc of this_ct = False- where- cls_nm = className cls- loop_found = not (isCTupleClass cls) && cls_nm `elemNameSet` rec_clss- -- Tuples never contribute to recursion, and can be nested- rec_clss' = rec_clss `extendNameSet` cls_nm-- this_ct | null tvs, null theta- = CDictCan { cc_ev = ev, cc_class = cls, cc_tyargs = tys- , cc_pend_sc = loop_found }- -- NB: If there is a loop, we cut off, so we have not- -- added the superclasses, hence cc_pend_sc = True- | otherwise- = CQuantCan (QCI { qci_tvs = tvs, qci_pred = mkClassPred cls tys- , qci_ev = ev- , qci_pend_sc = loop_found })---{- Note [Equality superclasses in quantified constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider (#15359, #15593, #15625)- f :: (forall a. theta => a ~ b) => stuff--It's a bit odd to have a local, quantified constraint for `(a~b)`,-but some people want such a thing (see the tickets). And for-Coercible it is definitely useful- f :: forall m. (forall p q. Coercible p q => Coercible (m p) (m q)))- => stuff--Moreover it's not hard to arrange; we just need to look up /equality/-constraints in the quantified-constraint environment, which we do in-GHC.Tc.Solver.Interact.doTopReactOther.--There is a wrinkle though, in the case where 'theta' is empty, so-we have- f :: (forall a. a~b) => stuff--Now, potentially, the superclass machinery kicks in, in-makeSuperClasses, giving us a a second quantified constraint- (forall a. a ~# b)-BUT this is an unboxed value! And nothing has prepared us for-dictionary "functions" that are unboxed. Actually it does just-about work, but the simplifier ends up with stuff like- case (/\a. eq_sel d) of df -> ...(df @Int)...-and fails to simplify that any further. And it doesn't satisfy-isPredTy any more.--So for now we simply decline to take superclasses in the quantified-case. Instead we have a special case in GHC.Tc.Solver.Interact.doTopReactOther,-which looks for primitive equalities specially in the quantified-constraints.--See also Note [Evidence for quantified constraints] in GHC.Core.Predicate.---************************************************************************-* *-* Irreducibles canonicalization-* *-************************************************************************--}--canIrred :: CtIrredStatus -> CtEvidence -> TcS (StopOrContinue Ct)--- Precondition: ty not a tuple and no other evidence form-canIrred status ev- = do { let pred = ctEvPred ev- ; traceTcS "can_pred" (text "IrredPred = " <+> ppr pred)- ; (xi,co) <- flatten FM_FlattenAll ev pred -- co :: xi ~ pred- ; rewriteEvidence ev xi co `andWhenContinue` \ new_ev ->-- do { -- Re-classify, in case flattening has improved its shape- -- Code is like the CNonCanonical case of canonicalize, except- -- that the IrredPred branch stops work- ; case classifyPredType (ctEvPred new_ev) of- ClassPred cls tys -> canClassNC new_ev cls tys- EqPred eq_rel ty1 ty2 -> canEqNC new_ev eq_rel ty1 ty2- ForAllPred tvs th p -> do traceTcS "canEvNC:forall" (ppr pred)- canForAllNC ev tvs th p- IrredPred {} -> continueWith $- mkIrredCt status new_ev } }--{- *********************************************************************-* *-* Quantified predicates-* *-********************************************************************* -}--{- Note [Quantified constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The -XQuantifiedConstraints extension allows type-class contexts like this:-- data Rose f x = Rose x (f (Rose f x))-- instance (Eq a, forall b. Eq b => Eq (f b))- => Eq (Rose f a) where- (Rose x1 rs1) == (Rose x2 rs2) = x1==x2 && rs1 == rs2--Note the (forall b. Eq b => Eq (f b)) in the instance contexts.-This quantified constraint is needed to solve the- [W] (Eq (f (Rose f x)))-constraint which arises form the (==) definition.--The wiki page is- https://gitlab.haskell.org/ghc/ghc/wikis/quantified-constraints-which in turn contains a link to the GHC Proposal where the change-is specified, and a Haskell Symposium paper about it.--We implement two main extensions to the design in the paper:-- 1. We allow a variable in the instance head, e.g.- f :: forall m a. (forall b. m b) => D (m a)- Notice the 'm' in the head of the quantified constraint, not- a class.-- 2. We support superclasses to quantified constraints.- For example (contrived):- f :: (Ord b, forall b. Ord b => Ord (m b)) => m a -> m a -> Bool- f x y = x==y- Here we need (Eq (m a)); but the quantified constraint deals only- with Ord. But we can make it work by using its superclass.--Here are the moving parts- * Language extension {-# LANGUAGE QuantifiedConstraints #-}- and add it to ghc-boot-th:GHC.LanguageExtensions.Type.Extension-- * A new form of evidence, EvDFun, that is used to discharge- such wanted constraints-- * checkValidType gets some changes to accept forall-constraints- only in the right places.-- * Predicate.Pred gets a new constructor ForAllPred, and- and classifyPredType analyses a PredType to decompose- the new forall-constraints-- * GHC.Tc.Solver.Monad.InertCans gets an extra field, inert_insts,- which holds all the Given forall-constraints. In effect,- such Given constraints are like local instance decls.-- * When trying to solve a class constraint, via- GHC.Tc.Solver.Interact.matchInstEnv, use the InstEnv from inert_insts- so that we include the local Given forall-constraints- in the lookup. (See GHC.Tc.Solver.Monad.getInstEnvs.)-- * GHC.Tc.Solver.Canonical.canForAll deals with solving a- forall-constraint. See- Note [Solving a Wanted forall-constraint]-- * We augment the kick-out code to kick out an inert- forall constraint if it can be rewritten by a new- type equality; see GHC.Tc.Solver.Monad.kick_out_rewritable--Note that a quantified constraint is never /inferred/-(by GHC.Tc.Solver.simplifyInfer). A function can only have a-quantified constraint in its type if it is given an explicit-type signature.---}--canForAllNC :: CtEvidence -> [TyVar] -> TcThetaType -> TcPredType- -> TcS (StopOrContinue Ct)-canForAllNC ev tvs theta pred- | isGiven ev -- See Note [Eagerly expand given superclasses]- , Just (cls, tys) <- cls_pred_tys_maybe- = do { sc_cts <- mkStrictSuperClasses ev tvs theta cls tys- ; emitWork sc_cts- ; canForAll ev False }-- | otherwise- = canForAll ev (isJust cls_pred_tys_maybe)-- where- cls_pred_tys_maybe = getClassPredTys_maybe pred--canForAll :: CtEvidence -> Bool -> TcS (StopOrContinue Ct)--- We have a constraint (forall as. blah => C tys)-canForAll ev pend_sc- = do { -- First rewrite it to apply the current substitution- -- Do not bother with type-family reductions; we can't- -- do them under a forall anyway (c.f. Flatten.flatten_one- -- on a forall type)- let pred = ctEvPred ev- ; (xi,co) <- flatten FM_SubstOnly ev pred -- co :: xi ~ pred- ; rewriteEvidence ev xi co `andWhenContinue` \ new_ev ->-- do { -- Now decompose into its pieces and solve it- -- (It takes a lot less code to flatten before decomposing.)- ; case classifyPredType (ctEvPred new_ev) of- ForAllPred tvs theta pred- -> solveForAll new_ev tvs theta pred pend_sc- _ -> pprPanic "canForAll" (ppr new_ev)- } }--solveForAll :: CtEvidence -> [TyVar] -> TcThetaType -> PredType -> Bool- -> TcS (StopOrContinue Ct)-solveForAll ev tvs theta pred pend_sc- | CtWanted { ctev_dest = dest } <- ev- = -- See Note [Solving a Wanted forall-constraint]- do { let skol_info = QuantCtxtSkol- empty_subst = mkEmptyTCvSubst $ mkInScopeSet $- tyCoVarsOfTypes (pred:theta) `delVarSetList` tvs- ; (subst, skol_tvs) <- tcInstSkolTyVarsX empty_subst tvs- ; given_ev_vars <- mapM newEvVar (substTheta subst theta)-- ; (lvl, (w_id, wanteds))- <- pushLevelNoWorkList (ppr skol_info) $- do { wanted_ev <- newWantedEvVarNC loc $- substTy subst pred- ; return ( ctEvEvId wanted_ev- , unitBag (mkNonCanonical wanted_ev)) }-- ; ev_binds <- emitImplicationTcS lvl skol_info skol_tvs- given_ev_vars wanteds-- ; setWantedEvTerm dest $- EvFun { et_tvs = skol_tvs, et_given = given_ev_vars- , et_binds = ev_binds, et_body = w_id }-- ; stopWith ev "Wanted forall-constraint" }-- | isGiven ev -- See Note [Solving a Given forall-constraint]- = do { addInertForAll qci- ; stopWith ev "Given forall-constraint" }-- | otherwise- = do { traceTcS "discarding derived forall-constraint" (ppr ev)- ; stopWith ev "Derived forall-constraint" }- where- loc = ctEvLoc ev- qci = QCI { qci_ev = ev, qci_tvs = tvs- , qci_pred = pred, qci_pend_sc = pend_sc }--{- Note [Solving a Wanted forall-constraint]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Solving a wanted forall (quantified) constraint- [W] df :: forall ab. (Eq a, Ord b) => C x a b-is delightfully easy. Just build an implication constraint- forall ab. (g1::Eq a, g2::Ord b) => [W] d :: C x a-and discharge df thus:- df = /\ab. \g1 g2. let <binds> in d-where <binds> is filled in by solving the implication constraint.-All the machinery is to hand; there is little to do.--Note [Solving a Given forall-constraint]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-For a Given constraint- [G] df :: forall ab. (Eq a, Ord b) => C x a b-we just add it to TcS's local InstEnv of known instances,-via addInertForall. Then, if we look up (C x Int Bool), say,-we'll find a match in the InstEnv.---************************************************************************-* *-* Equalities-* *-************************************************************************--Note [Canonicalising equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-In order to canonicalise an equality, we look at the structure of the-two types at hand, looking for similarities. A difficulty is that the-types may look dissimilar before flattening but similar after flattening.-However, we don't just want to jump in and flatten right away, because-this might be wasted effort. So, after looking for similarities and failing,-we flatten and then try again. Of course, we don't want to loop, so we-track whether or not we've already flattened.--It is conceivable to do a better job at tracking whether or not a type-is flattened, but this is left as future work. (Mar '15)---Note [Decomposing FunTy]-~~~~~~~~~~~~~~~~~~~~~~~~-can_eq_nc' may attempt to decompose a FunTy that is un-zonked. This-means that we may very well have a FunTy containing a type of some-unknown kind. For instance, we may have,-- FunTy (a :: k) Int--Where k is a unification variable. So the calls to getRuntimeRep_maybe may-fail (returning Nothing). In that case we'll fall through, zonk, and try again.-Zonking should fill the variable k, meaning that decomposition will succeed the-second time around.--Also note that we require the AnonArgFlag to match. This will stop-us decomposing- (Int -> Bool) ~ (Show a => blah)-It's as if we treat (->) and (=>) as different type constructors.--}--canEqNC :: CtEvidence -> EqRel -> Type -> Type -> TcS (StopOrContinue Ct)-canEqNC ev eq_rel ty1 ty2- = do { result <- zonk_eq_types ty1 ty2- ; case result of- Left (Pair ty1' ty2') -> can_eq_nc False ev eq_rel ty1' ty1 ty2' ty2- Right ty -> canEqReflexive ev eq_rel ty }--can_eq_nc- :: Bool -- True => both types are flat- -> CtEvidence- -> EqRel- -> Type -> Type -- LHS, after and before type-synonym expansion, resp- -> Type -> Type -- RHS, after and before type-synonym expansion, resp- -> TcS (StopOrContinue Ct)-can_eq_nc flat ev eq_rel ty1 ps_ty1 ty2 ps_ty2- = do { traceTcS "can_eq_nc" $- vcat [ ppr flat, ppr ev, ppr eq_rel, ppr ty1, ppr ps_ty1, ppr ty2, ppr ps_ty2 ]- ; rdr_env <- getGlobalRdrEnvTcS- ; fam_insts <- getFamInstEnvs- ; can_eq_nc' flat rdr_env fam_insts ev eq_rel ty1 ps_ty1 ty2 ps_ty2 }--can_eq_nc'- :: Bool -- True => both input types are flattened- -> GlobalRdrEnv -- needed to see which newtypes are in scope- -> FamInstEnvs -- needed to unwrap data instances- -> CtEvidence- -> EqRel- -> Type -> Type -- LHS, after and before type-synonym expansion, resp- -> Type -> Type -- RHS, after and before type-synonym expansion, resp- -> TcS (StopOrContinue Ct)---- Expand synonyms first; see Note [Type synonyms and canonicalization]-can_eq_nc' flat rdr_env envs ev eq_rel ty1 ps_ty1 ty2 ps_ty2- | Just ty1' <- tcView ty1 = can_eq_nc' flat rdr_env envs ev eq_rel ty1' ps_ty1 ty2 ps_ty2- | Just ty2' <- tcView ty2 = can_eq_nc' flat rdr_env envs ev eq_rel ty1 ps_ty1 ty2' ps_ty2---- need to check for reflexivity in the ReprEq case.--- See Note [Eager reflexivity check]--- Check only when flat because the zonk_eq_types check in canEqNC takes--- care of the non-flat case.-can_eq_nc' True _rdr_env _envs ev ReprEq ty1 _ ty2 _- | ty1 `tcEqType` ty2- = canEqReflexive ev ReprEq ty1---- When working with ReprEq, unwrap newtypes.--- See Note [Unwrap newtypes first]--- This must be above the TyVarTy case, in order to guarantee (TyEq:N)-can_eq_nc' _flat rdr_env envs ev eq_rel ty1 ps_ty1 ty2 ps_ty2- | ReprEq <- eq_rel- , Just stuff1 <- tcTopNormaliseNewTypeTF_maybe envs rdr_env ty1- = can_eq_newtype_nc ev NotSwapped ty1 stuff1 ty2 ps_ty2-- | ReprEq <- eq_rel- , Just stuff2 <- tcTopNormaliseNewTypeTF_maybe envs rdr_env ty2- = can_eq_newtype_nc ev IsSwapped ty2 stuff2 ty1 ps_ty1---- Then, get rid of casts-can_eq_nc' flat _rdr_env _envs ev eq_rel (CastTy ty1 co1) _ ty2 ps_ty2- | not (isTyVarTy ty2) -- See (3) in Note [Equalities with incompatible kinds]- = canEqCast flat ev eq_rel NotSwapped ty1 co1 ty2 ps_ty2-can_eq_nc' flat _rdr_env _envs ev eq_rel ty1 ps_ty1 (CastTy ty2 co2) _- | not (isTyVarTy ty1) -- See (3) in Note [Equalities with incompatible kinds]- = canEqCast flat ev eq_rel IsSwapped ty2 co2 ty1 ps_ty1---- NB: pattern match on True: we want only flat types sent to canEqTyVar.--- See also Note [No top-level newtypes on RHS of representational equalities]-can_eq_nc' True _rdr_env _envs ev eq_rel (TyVarTy tv1) ps_ty1 ty2 ps_ty2- = canEqTyVar ev eq_rel NotSwapped tv1 ps_ty1 ty2 ps_ty2-can_eq_nc' True _rdr_env _envs ev eq_rel ty1 ps_ty1 (TyVarTy tv2) ps_ty2- = canEqTyVar ev eq_rel IsSwapped tv2 ps_ty2 ty1 ps_ty1--------------------------- Otherwise try to decompose--------------------------- Literals-can_eq_nc' _flat _rdr_env _envs ev eq_rel ty1@(LitTy l1) _ (LitTy l2) _- | l1 == l2- = do { setEvBindIfWanted ev (evCoercion $ mkReflCo (eqRelRole eq_rel) ty1)- ; stopWith ev "Equal LitTy" }---- Decompose FunTy: (s -> t) and (c => t)--- NB: don't decompose (Int -> blah) ~ (Show a => blah)-can_eq_nc' _flat _rdr_env _envs ev eq_rel- (FunTy { ft_mult = am1, ft_af = af1, ft_arg = ty1a, ft_res = ty1b }) _- (FunTy { ft_mult = am2, ft_af = af2, ft_arg = ty2a, ft_res = ty2b }) _- | af1 == af2 -- Don't decompose (Int -> blah) ~ (Show a => blah)- , Just ty1a_rep <- getRuntimeRep_maybe ty1a -- getRutimeRep_maybe:- , Just ty1b_rep <- getRuntimeRep_maybe ty1b -- see Note [Decomposing FunTy]- , Just ty2a_rep <- getRuntimeRep_maybe ty2a- , Just ty2b_rep <- getRuntimeRep_maybe ty2b- = canDecomposableTyConAppOK ev eq_rel funTyCon- [am1, ty1a_rep, ty1b_rep, ty1a, ty1b]- [am2, ty2a_rep, ty2b_rep, ty2a, ty2b]---- Decompose type constructor applications--- NB: e have expanded type synonyms already-can_eq_nc' _flat _rdr_env _envs ev eq_rel- (TyConApp tc1 tys1) _- (TyConApp tc2 tys2) _- | not (isTypeFamilyTyCon tc1)- , not (isTypeFamilyTyCon tc2)- = canTyConApp ev eq_rel tc1 tys1 tc2 tys2--can_eq_nc' _flat _rdr_env _envs ev eq_rel- s1@(ForAllTy (Bndr _ vis1) _) _- s2@(ForAllTy (Bndr _ vis2) _) _- | vis1 `sameVis` vis2 -- Note [ForAllTy and typechecker equality]- = can_eq_nc_forall ev eq_rel s1 s2---- See Note [Canonicalising type applications] about why we require flat types-can_eq_nc' True _rdr_env _envs ev eq_rel (AppTy t1 s1) _ ty2 _- | NomEq <- eq_rel- , Just (t2, s2) <- tcSplitAppTy_maybe ty2- = can_eq_app ev t1 s1 t2 s2-can_eq_nc' True _rdr_env _envs ev eq_rel ty1 _ (AppTy t2 s2) _- | NomEq <- eq_rel- , Just (t1, s1) <- tcSplitAppTy_maybe ty1- = can_eq_app ev t1 s1 t2 s2---- No similarity in type structure detected. Flatten and try again.-can_eq_nc' False rdr_env envs ev eq_rel _ ps_ty1 _ ps_ty2- = do { (xi1, co1) <- flatten FM_FlattenAll ev ps_ty1- ; (xi2, co2) <- flatten FM_FlattenAll ev ps_ty2- ; new_ev <- rewriteEqEvidence ev NotSwapped xi1 xi2 co1 co2- ; can_eq_nc' True rdr_env envs new_ev eq_rel xi1 xi1 xi2 xi2 }---- We've flattened and the types don't match. Give up.-can_eq_nc' True _rdr_env _envs ev eq_rel _ ps_ty1 _ ps_ty2- = do { traceTcS "can_eq_nc' catch-all case" (ppr ps_ty1 $$ ppr ps_ty2)- ; case eq_rel of -- See Note [Unsolved equalities]- ReprEq -> continueWith (mkIrredCt OtherCIS ev)- NomEq -> continueWith (mkIrredCt InsolubleCIS ev) }- -- No need to call canEqFailure/canEqHardFailure because they- -- flatten, and the types involved here are already flat--{- Note [Unsolved equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-If we have an unsolved equality like- (a b ~R# Int)-that is not necessarily insoluble! Maybe 'a' will turn out to be a newtype.-So we want to make it a potentially-soluble Irred not an insoluble one.-Missing this point is what caused #15431--Note [ForAllTy and typechecker equality]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Should GHC type-check the following program (adapted from #15740)?-- {-# LANGUAGE PolyKinds, ... #-}- data D a- type family F :: forall k. k -> Type- type instance F = D--Due to the way F is declared, any instance of F must have a right-hand side-whose kind is equal to `forall k. k -> Type`. The kind of D is-`forall {k}. k -> Type`, which is very close, but technically uses distinct-Core:-- ------------------------------------------------------------ | Source Haskell | Core |- ------------------------------------------------------------ | forall k. <...> | ForAllTy (Bndr k Specified) (<...>) |- | forall {k}. <...> | ForAllTy (Bndr k Inferred) (<...>) |- -------------------------------------------------------------We could deem these kinds to be unequal, but that would imply rejecting-programs like the one above. Whether a kind variable binder ends up being-specified or inferred can be somewhat subtle, however, especially for kinds-that aren't explicitly written out in the source code (like in D above).-For now, we decide to not make the specified/inferred status of an invisible-type variable binder affect GHC's notion of typechecker equality-(see Note [Typechecker equality vs definitional equality] in-GHC.Tc.Utils.TcType). That is, we have the following:-- --------------------------------------------------- | Type 1 | Type 2 | Equal? |- --------------------|------------------------------ | forall k. <...> | forall k. <...> | Yes |- | | forall {k}. <...> | Yes |- | | forall k -> <...> | No |- --------------------------------------------------- | forall {k}. <...> | forall k. <...> | Yes |- | | forall {k}. <...> | Yes |- | | forall k -> <...> | No |- --------------------------------------------------- | forall k -> <...> | forall k. <...> | No |- | | forall {k}. <...> | No |- | | forall k -> <...> | Yes |- ----------------------------------------------------We implement this nuance by using the GHC.Types.Var.sameVis function in-GHC.Tc.Solver.Canonical.canEqNC and GHC.Tc.Utils.TcType.tcEqType, which-respect typechecker equality. sameVis puts both forms of invisible type-variable binders into the same equivalence class.--Note that we do /not/ use sameVis in GHC.Core.Type.eqType, which implements-/definitional/ equality, a slighty more coarse-grained notion of equality-(see Note [Non-trivial definitional equality] in GHC.Core.TyCo.Rep) that does-not consider the ArgFlag of ForAllTys at all. That is, eqType would equate all-of forall k. <...>, forall {k}. <...>, and forall k -> <...>.--}------------------------------------can_eq_nc_forall :: CtEvidence -> EqRel- -> Type -> Type -- LHS and RHS- -> TcS (StopOrContinue Ct)--- (forall as. phi1) ~ (forall bs. phi2)--- Check for length match of as, bs--- Then build an implication constraint: forall as. phi1 ~ phi2[as/bs]--- But remember also to unify the kinds of as and bs--- (this is the 'go' loop), and actually substitute phi2[as |> cos / bs]--- Remember also that we might have forall z (a:z). blah--- so we must proceed one binder at a time (#13879)--can_eq_nc_forall ev eq_rel s1 s2- | CtWanted { ctev_loc = loc, ctev_dest = orig_dest } <- ev- = do { let free_tvs = tyCoVarsOfTypes [s1,s2]- (bndrs1, phi1) = tcSplitForAllTyVarBinders s1- (bndrs2, phi2) = tcSplitForAllTyVarBinders s2- ; if not (equalLength bndrs1 bndrs2)- then do { traceTcS "Forall failure" $- vcat [ ppr s1, ppr s2, ppr bndrs1, ppr bndrs2- , ppr (map binderArgFlag bndrs1)- , ppr (map binderArgFlag bndrs2) ]- ; canEqHardFailure ev s1 s2 }- else- do { traceTcS "Creating implication for polytype equality" $ ppr ev- ; let empty_subst1 = mkEmptyTCvSubst $ mkInScopeSet free_tvs- ; (subst1, skol_tvs) <- tcInstSkolTyVarsX empty_subst1 $- binderVars bndrs1-- ; let skol_info = UnifyForAllSkol phi1- phi1' = substTy subst1 phi1-- -- Unify the kinds, extend the substitution- go :: [TcTyVar] -> TCvSubst -> [TyVarBinder]- -> TcS (TcCoercion, Cts)- go (skol_tv:skol_tvs) subst (bndr2:bndrs2)- = do { let tv2 = binderVar bndr2- ; (kind_co, wanteds1) <- unify loc Nominal (tyVarKind skol_tv)- (substTy subst (tyVarKind tv2))- ; let subst' = extendTvSubstAndInScope subst tv2- (mkCastTy (mkTyVarTy skol_tv) kind_co)- -- skol_tv is already in the in-scope set, but the- -- free vars of kind_co are not; hence "...AndInScope"- ; (co, wanteds2) <- go skol_tvs subst' bndrs2- ; return ( mkTcForAllCo skol_tv kind_co co- , wanteds1 `unionBags` wanteds2 ) }-- -- Done: unify phi1 ~ phi2- go [] subst bndrs2- = ASSERT( null bndrs2 )- unify loc (eqRelRole eq_rel) phi1' (substTyUnchecked subst phi2)-- go _ _ _ = panic "cna_eq_nc_forall" -- case (s:ss) []-- empty_subst2 = mkEmptyTCvSubst (getTCvInScope subst1)-- ; (lvl, (all_co, wanteds)) <- pushLevelNoWorkList (ppr skol_info) $- go skol_tvs empty_subst2 bndrs2- ; emitTvImplicationTcS lvl skol_info skol_tvs wanteds-- ; setWantedEq orig_dest all_co- ; stopWith ev "Deferred polytype equality" } }-- | otherwise- = do { traceTcS "Omitting decomposition of given polytype equality" $- pprEq s1 s2 -- See Note [Do not decompose given polytype equalities]- ; stopWith ev "Discard given polytype equality" }-- where- unify :: CtLoc -> Role -> TcType -> TcType -> TcS (TcCoercion, Cts)- -- This version returns the wanted constraint rather- -- than putting it in the work list- unify loc role ty1 ty2- | ty1 `tcEqType` ty2- = return (mkTcReflCo role ty1, emptyBag)- | otherwise- = do { (wanted, co) <- newWantedEq loc role ty1 ty2- ; return (co, unitBag (mkNonCanonical wanted)) }-------------------------------------- | Compare types for equality, while zonking as necessary. Gives up--- as soon as it finds that two types are not equal.--- This is quite handy when some unification has made two--- types in an inert Wanted to be equal. We can discover the equality without--- flattening, which is sometimes very expensive (in the case of type functions).--- In particular, this function makes a ~20% improvement in test case--- perf/compiler/T5030.------ Returns either the (partially zonked) types in the case of--- inequality, or the one type in the case of equality. canEqReflexive is--- a good next step in the 'Right' case. Returning 'Left' is always safe.------ NB: This does *not* look through type synonyms. In fact, it treats type--- synonyms as rigid constructors. In the future, it might be convenient--- to look at only those arguments of type synonyms that actually appear--- in the synonym RHS. But we're not there yet.-zonk_eq_types :: TcType -> TcType -> TcS (Either (Pair TcType) TcType)-zonk_eq_types = go- where- go (TyVarTy tv1) (TyVarTy tv2) = tyvar_tyvar tv1 tv2- go (TyVarTy tv1) ty2 = tyvar NotSwapped tv1 ty2- go ty1 (TyVarTy tv2) = tyvar IsSwapped tv2 ty1-- -- We handle FunTys explicitly here despite the fact that they could also be- -- treated as an application. Why? Well, for one it's cheaper to just look- -- at two types (the argument and result types) than four (the argument,- -- result, and their RuntimeReps). Also, we haven't completely zonked yet,- -- so we may run into an unzonked type variable while trying to compute the- -- RuntimeReps of the argument and result types. This can be observed in- -- testcase tc269.- go ty1 ty2- | Just (Scaled w1 arg1, res1) <- split1- , Just (Scaled w2 arg2, res2) <- split2- , eqType w1 w2- = do { res_a <- go arg1 arg2- ; res_b <- go res1 res2- ; return $ combine_rev (mkVisFunTy w1) res_b res_a- }- | isJust split1 || isJust split2- = bale_out ty1 ty2- where- split1 = tcSplitFunTy_maybe ty1- split2 = tcSplitFunTy_maybe ty2-- go ty1 ty2- | Just (tc1, tys1) <- repSplitTyConApp_maybe ty1- , Just (tc2, tys2) <- repSplitTyConApp_maybe ty2- = if tc1 == tc2 && tys1 `equalLength` tys2- -- Crucial to check for equal-length args, because- -- we cannot assume that the two args to 'go' have- -- the same kind. E.g go (Proxy * (Maybe Int))- -- (Proxy (*->*) Maybe)- -- We'll call (go (Maybe Int) Maybe)- -- See #13083- then tycon tc1 tys1 tys2- else bale_out ty1 ty2-- go ty1 ty2- | Just (ty1a, ty1b) <- tcRepSplitAppTy_maybe ty1- , Just (ty2a, ty2b) <- tcRepSplitAppTy_maybe ty2- = do { res_a <- go ty1a ty2a- ; res_b <- go ty1b ty2b- ; return $ combine_rev mkAppTy res_b res_a }-- go ty1@(LitTy lit1) (LitTy lit2)- | lit1 == lit2- = return (Right ty1)-- go ty1 ty2 = bale_out ty1 ty2- -- We don't handle more complex forms here-- bale_out ty1 ty2 = return $ Left (Pair ty1 ty2)-- tyvar :: SwapFlag -> TcTyVar -> TcType- -> TcS (Either (Pair TcType) TcType)- -- Try to do as little as possible, as anything we do here is redundant- -- with flattening. In particular, no need to zonk kinds. That's why- -- we don't use the already-defined zonking functions- tyvar swapped tv ty- = case tcTyVarDetails tv of- MetaTv { mtv_ref = ref }- -> do { cts <- readTcRef ref- ; case cts of- Flexi -> give_up- Indirect ty' -> do { trace_indirect tv ty'- ; unSwap swapped go ty' ty } }- _ -> give_up- where- give_up = return $ Left $ unSwap swapped Pair (mkTyVarTy tv) ty-- tyvar_tyvar tv1 tv2- | tv1 == tv2 = return (Right (mkTyVarTy tv1))- | otherwise = do { (ty1', progress1) <- quick_zonk tv1- ; (ty2', progress2) <- quick_zonk tv2- ; if progress1 || progress2- then go ty1' ty2'- else return $ Left (Pair (TyVarTy tv1) (TyVarTy tv2)) }-- trace_indirect tv ty- = traceTcS "Following filled tyvar (zonk_eq_types)"- (ppr tv <+> equals <+> ppr ty)-- quick_zonk tv = case tcTyVarDetails tv of- MetaTv { mtv_ref = ref }- -> do { cts <- readTcRef ref- ; case cts of- Flexi -> return (TyVarTy tv, False)- Indirect ty' -> do { trace_indirect tv ty'- ; return (ty', True) } }- _ -> return (TyVarTy tv, False)-- -- This happens for type families, too. But recall that failure- -- here just means to try harder, so it's OK if the type function- -- isn't injective.- tycon :: TyCon -> [TcType] -> [TcType]- -> TcS (Either (Pair TcType) TcType)- tycon tc tys1 tys2- = do { results <- zipWithM go tys1 tys2- ; return $ case combine_results results of- Left tys -> Left (mkTyConApp tc <$> tys)- Right tys -> Right (mkTyConApp tc tys) }-- combine_results :: [Either (Pair TcType) TcType]- -> Either (Pair [TcType]) [TcType]- combine_results = bimap (fmap reverse) reverse .- foldl' (combine_rev (:)) (Right [])-- -- combine (in reverse) a new result onto an already-combined result- combine_rev :: (a -> b -> c)- -> Either (Pair b) b- -> Either (Pair a) a- -> Either (Pair c) c- combine_rev f (Left list) (Left elt) = Left (f <$> elt <*> list)- combine_rev f (Left list) (Right ty) = Left (f <$> pure ty <*> list)- combine_rev f (Right tys) (Left elt) = Left (f <$> elt <*> pure tys)- combine_rev f (Right tys) (Right ty) = Right (f ty tys)--{- See Note [Unwrap newtypes first]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider- newtype N m a = MkN (m a)-Then N will get a conservative, Nominal role for its second parameter 'a',-because it appears as an argument to the unknown 'm'. Now consider- [W] N Maybe a ~R# N Maybe b--If we decompose, we'll get- [W] a ~N# b--But if instead we unwrap we'll get- [W] Maybe a ~R# Maybe b-which in turn gives us- [W] a ~R# b-which is easier to satisfy.--Bottom line: unwrap newtypes before decomposing them!-c.f. #9123 comment:52,53 for a compelling example.--Note [Newtypes can blow the stack]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we have-- newtype X = MkX (Int -> X)- newtype Y = MkY (Int -> Y)--and now wish to prove-- [W] X ~R Y--This Wanted will loop, expanding out the newtypes ever deeper looking-for a solid match or a solid discrepancy. Indeed, there is something-appropriate to this looping, because X and Y *do* have the same representation,-in the limit -- they're both (Fix ((->) Int)). However, no finitely-sized-coercion will ever witness it. This loop won't actually cause GHC to hang,-though, because we check our depth when unwrapping newtypes.--Note [Eager reflexivity check]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we have-- newtype X = MkX (Int -> X)--and-- [W] X ~R X--Naively, we would start unwrapping X and end up in a loop. Instead,-we do this eager reflexivity check. This is necessary only for representational-equality because the flattener technology deals with the similar case-(recursive type families) for nominal equality.--Note that this check does not catch all cases, but it will catch the cases-we're most worried about, types like X above that are actually inhabited.--Here's another place where this reflexivity check is key:-Consider trying to prove (f a) ~R (f a). The AppTys in there can't-be decomposed, because representational equality isn't congruent with respect-to AppTy. So, when canonicalising the equality above, we get stuck and-would normally produce a CIrredCan. However, we really do want to-be able to solve (f a) ~R (f a). So, in the representational case only,-we do a reflexivity check.--(This would be sound in the nominal case, but unnecessary, and I [Richard-E.] am worried that it would slow down the common case.)--}----------------------------- | We're able to unwrap a newtype. Update the bits accordingly.-can_eq_newtype_nc :: CtEvidence -- ^ :: ty1 ~ ty2- -> SwapFlag- -> TcType -- ^ ty1- -> ((Bag GlobalRdrElt, TcCoercion), TcType) -- ^ :: ty1 ~ ty1'- -> TcType -- ^ ty2- -> TcType -- ^ ty2, with type synonyms- -> TcS (StopOrContinue Ct)-can_eq_newtype_nc ev swapped ty1 ((gres, co), ty1') ty2 ps_ty2- = do { traceTcS "can_eq_newtype_nc" $- vcat [ ppr ev, ppr swapped, ppr co, ppr gres, ppr ty1', ppr ty2 ]-- -- check for blowing our stack:- -- See Note [Newtypes can blow the stack]- ; checkReductionDepth (ctEvLoc ev) ty1-- -- Next, we record uses of newtype constructors, since coercing- -- through newtypes is tantamount to using their constructors.- ; addUsedGREs gre_list- -- If a newtype constructor was imported, don't warn about not- -- importing it...- ; traverse_ keepAlive $ map gre_name gre_list- -- ...and similarly, if a newtype constructor was defined in the same- -- module, don't warn about it being unused.- -- See Note [Tracking unused binding and imports] in GHC.Tc.Utils.-- ; new_ev <- rewriteEqEvidence ev swapped ty1' ps_ty2- (mkTcSymCo co) (mkTcReflCo Representational ps_ty2)- ; can_eq_nc False new_ev ReprEq ty1' ty1' ty2 ps_ty2 }- where- gre_list = bagToList gres-------------- ^ Decompose a type application.--- All input types must be flat. See Note [Canonicalising type applications]--- Nominal equality only!-can_eq_app :: CtEvidence -- :: s1 t1 ~N s2 t2- -> Xi -> Xi -- s1 t1- -> Xi -> Xi -- s2 t2- -> TcS (StopOrContinue Ct)---- AppTys only decompose for nominal equality, so this case just leads--- to an irreducible constraint; see typecheck/should_compile/T10494--- See Note [Decomposing equality], note {4}-can_eq_app ev s1 t1 s2 t2- | CtDerived {} <- ev- = do { unifyDeriveds loc [Nominal, Nominal] [s1, t1] [s2, t2]- ; stopWith ev "Decomposed [D] AppTy" }-- | CtWanted { ctev_dest = dest } <- ev- = do { co_s <- unifyWanted loc Nominal s1 s2- ; let arg_loc- | isNextArgVisible s1 = loc- | otherwise = updateCtLocOrigin loc toInvisibleOrigin- ; co_t <- unifyWanted arg_loc Nominal t1 t2- ; let co = mkAppCo co_s co_t- ; setWantedEq dest co- ; stopWith ev "Decomposed [W] AppTy" }-- -- If there is a ForAll/(->) mismatch, the use of the Left coercion- -- below is ill-typed, potentially leading to a panic in splitTyConApp- -- Test case: typecheck/should_run/Typeable1- -- We could also include this mismatch check above (for W and D), but it's slow- -- and we'll get a better error message not doing it- | s1k `mismatches` s2k- = canEqHardFailure ev (s1 `mkAppTy` t1) (s2 `mkAppTy` t2)-- | CtGiven { ctev_evar = evar } <- ev- = do { let co = mkTcCoVarCo evar- co_s = mkTcLRCo CLeft co- co_t = mkTcLRCo CRight co- ; evar_s <- newGivenEvVar loc ( mkTcEqPredLikeEv ev s1 s2- , evCoercion co_s )- ; evar_t <- newGivenEvVar loc ( mkTcEqPredLikeEv ev t1 t2- , evCoercion co_t )- ; emitWorkNC [evar_t]- ; canEqNC evar_s NomEq s1 s2 }-- where- loc = ctEvLoc ev-- s1k = tcTypeKind s1- s2k = tcTypeKind s2-- k1 `mismatches` k2- = isForAllTy k1 && not (isForAllTy k2)- || not (isForAllTy k1) && isForAllTy k2---------------------------- | Break apart an equality over a casted type--- looking like (ty1 |> co1) ~ ty2 (modulo a swap-flag)-canEqCast :: Bool -- are both types flat?- -> CtEvidence- -> EqRel- -> SwapFlag- -> TcType -> Coercion -- LHS (res. RHS), ty1 |> co1- -> TcType -> TcType -- RHS (res. LHS), ty2 both normal and pretty- -> TcS (StopOrContinue Ct)-canEqCast flat ev eq_rel swapped ty1 co1 ty2 ps_ty2- = do { traceTcS "Decomposing cast" (vcat [ ppr ev- , ppr ty1 <+> text "|>" <+> ppr co1- , ppr ps_ty2 ])- ; new_ev <- rewriteEqEvidence ev swapped ty1 ps_ty2- (mkTcGReflRightCo role ty1 co1)- (mkTcReflCo role ps_ty2)- ; can_eq_nc flat new_ev eq_rel ty1 ty1 ty2 ps_ty2 }- where- role = eqRelRole eq_rel---------------------------canTyConApp :: CtEvidence -> EqRel- -> TyCon -> [TcType]- -> TyCon -> [TcType]- -> TcS (StopOrContinue Ct)--- See Note [Decomposing TyConApps]--- Neither tc1 nor tc2 is a saturated funTyCon-canTyConApp ev eq_rel tc1 tys1 tc2 tys2- | tc1 == tc2- , tys1 `equalLength` tys2- = do { inerts <- getTcSInerts- ; if can_decompose inerts- then canDecomposableTyConAppOK ev eq_rel tc1 tys1 tys2- else canEqFailure ev eq_rel ty1 ty2 }-- -- See Note [Skolem abstract data] (at tyConSkolem)- | tyConSkolem tc1 || tyConSkolem tc2- = do { traceTcS "canTyConApp: skolem abstract" (ppr tc1 $$ ppr tc2)- ; continueWith (mkIrredCt OtherCIS ev) }-- -- Fail straight away for better error messages- -- See Note [Use canEqFailure in canDecomposableTyConApp]- | eq_rel == ReprEq && not (isGenerativeTyCon tc1 Representational &&- isGenerativeTyCon tc2 Representational)- = canEqFailure ev eq_rel ty1 ty2- | otherwise- = canEqHardFailure ev ty1 ty2- where- -- Reconstruct the types for error messages. This would do- -- the wrong thing (from a pretty printing point of view)- -- for functions, because we've lost the AnonArgFlag; but- -- in fact we never call canTyConApp on a saturated FunTyCon- ty1 = mkTyConApp tc1 tys1- ty2 = mkTyConApp tc2 tys2-- loc = ctEvLoc ev- pred = ctEvPred ev-- -- See Note [Decomposing equality]- can_decompose inerts- = isInjectiveTyCon tc1 (eqRelRole eq_rel)- || (ctEvFlavour ev /= Given && isEmptyBag (matchableGivens loc pred inerts))--{--Note [Use canEqFailure in canDecomposableTyConApp]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We must use canEqFailure, not canEqHardFailure here, because there is-the possibility of success if working with a representational equality.-Here is one case:-- type family TF a where TF Char = Bool- data family DF a- newtype instance DF Bool = MkDF Int--Suppose we are canonicalising (Int ~R DF (TF a)), where we don't yet-know `a`. This is *not* a hard failure, because we might soon learn-that `a` is, in fact, Char, and then the equality succeeds.--Here is another case:-- [G] Age ~R Int--where Age's constructor is not in scope. We don't want to report-an "inaccessible code" error in the context of this Given!--For example, see typecheck/should_compile/T10493, repeated here:-- import Data.Ord (Down) -- no constructor-- foo :: Coercible (Down Int) Int => Down Int -> Int- foo = coerce--That should compile, but only because we use canEqFailure and not-canEqHardFailure.--Note [Decomposing equality]-~~~~~~~~~~~~~~~~~~~~~~~~~~~-If we have a constraint (of any flavour and role) that looks like-T tys1 ~ T tys2, what can we conclude about tys1 and tys2? The answer,-of course, is "it depends". This Note spells it all out.--In this Note, "decomposition" refers to taking the constraint- [fl] (T tys1 ~X T tys2)-(for some flavour fl and some role X) and replacing it with- [fls'] (tys1 ~Xs' tys2)-where that notation indicates a list of new constraints, where the-new constraints may have different flavours and different roles.--The key property to consider is injectivity. When decomposing a Given the-decomposition is sound if and only if T is injective in all of its type-arguments. When decomposing a Wanted, the decomposition is sound (assuming the-correct roles in the produced equality constraints), but it may be a guess ---that is, an unforced decision by the constraint solver. Decomposing Wanteds-over injective TyCons does not entail guessing. But sometimes we want to-decompose a Wanted even when the TyCon involved is not injective! (See below.)--So, in broad strokes, we want this rule:--(*) Decompose a constraint (T tys1 ~X T tys2) if and only if T is injective-at role X.--Pursuing the details requires exploring three axes:-* Flavour: Given vs. Derived vs. Wanted-* Role: Nominal vs. Representational-* TyCon species: datatype vs. newtype vs. data family vs. type family vs. type variable--(So a type variable isn't a TyCon, but it's convenient to put the AppTy case-in the same table.)--Right away, we can say that Derived behaves just as Wanted for the purposes-of decomposition. The difference between Derived and Wanted is the handling of-evidence. Since decomposition in these cases isn't a matter of soundness but of-guessing, we want the same behavior regardless of evidence.--Here is a table (discussion following) detailing where decomposition of- (T s1 ... sn) ~r (T t1 .. tn)-is allowed. The first four lines (Data types ... type family) refer-to TyConApps with various TyCons T; the last line is for AppTy, where-there is presumably a type variable at the head, so it's actually- (s s1 ... sn) ~r (t t1 .. tn)--NOMINAL GIVEN WANTED--Datatype YES YES-Newtype YES YES-Data family YES YES-Type family YES, in injective args{1} YES, in injective args{1}-Type variable YES YES--REPRESENTATIONAL GIVEN WANTED--Datatype YES YES-Newtype NO{2} MAYBE{2}-Data family NO{3} MAYBE{3}-Type family NO NO-Type variable NO{4} NO{4}--{1}: Type families can be injective in some, but not all, of their arguments,-so we want to do partial decomposition. This is quite different than the way-other decomposition is done, where the decomposed equalities replace the original-one. We thus proceed much like we do with superclasses: emitting new Givens-when "decomposing" a partially-injective type family Given and new Deriveds-when "decomposing" a partially-injective type family Wanted. (As of the time of-writing, 13 June 2015, the implementation of injective type families has not-been merged, but it should be soon. Please delete this parenthetical if the-implementation is indeed merged.)--{2}: See Note [Decomposing newtypes at representational role]--{3}: Because of the possibility of newtype instances, we must treat-data families like newtypes. See also Note [Decomposing newtypes at-representational role]. See #10534 and test case-typecheck/should_fail/T10534.--{4}: Because type variables can stand in for newtypes, we conservatively do not-decompose AppTys over representational equality.--In the implementation of can_eq_nc and friends, we don't directly pattern-match using lines like in the tables above, as those tables don't cover-all cases (what about PrimTyCon? tuples?). Instead we just ask about injectivity,-boiling the tables above down to rule (*). The exceptions to rule (*) are for-injective type families, which are handled separately from other decompositions,-and the MAYBE entries above.--Note [Decomposing newtypes at representational role]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-This note discusses the 'newtype' line in the REPRESENTATIONAL table-in Note [Decomposing equality]. (At nominal role, newtypes are fully-decomposable.)--Here is a representative example of why representational equality over-newtypes is tricky:-- newtype Nt a = Mk Bool -- NB: a is not used in the RHS,- type role Nt representational -- but the user gives it an R role anyway--If we have [W] Nt alpha ~R Nt beta, we *don't* want to decompose to-[W] alpha ~R beta, because it's possible that alpha and beta aren't-representationally equal. Here's another example.-- newtype Nt a = MkNt (Id a)- type family Id a where Id a = a-- [W] Nt Int ~R Nt Age--Because of its use of a type family, Nt's parameter will get inferred to have-a nominal role. Thus, decomposing the wanted will yield [W] Int ~N Age, which-is unsatisfiable. Unwrapping, though, leads to a solution.--Conclusion:- * Unwrap newtypes before attempting to decompose them.- This is done in can_eq_nc'.--It all comes from the fact that newtypes aren't necessarily injective-w.r.t. representational equality.--Furthermore, as explained in Note [NthCo and newtypes] in GHC.Core.TyCo.Rep, we can't use-NthCo on representational coercions over newtypes. NthCo comes into play-only when decomposing givens.--Conclusion:- * Do not decompose [G] N s ~R N t--Is it sensible to decompose *Wanted* constraints over newtypes? Yes!-It's the only way we could ever prove (IO Int ~R IO Age), recalling-that IO is a newtype.--However we must be careful. Consider-- type role Nt representational-- [G] Nt a ~R Nt b (1)- [W] NT alpha ~R Nt b (2)- [W] alpha ~ a (3)--If we focus on (3) first, we'll substitute in (2), and now it's-identical to the given (1), so we succeed. But if we focus on (2)-first, and decompose it, we'll get (alpha ~R b), which is not soluble.-This is exactly like the question of overlapping Givens for class-constraints: see Note [Instance and Given overlap] in GHC.Tc.Solver.Interact.--Conclusion:- * Decompose [W] N s ~R N t iff there no given constraint that could- later solve it.---}--canDecomposableTyConAppOK :: CtEvidence -> EqRel- -> TyCon -> [TcType] -> [TcType]- -> TcS (StopOrContinue Ct)--- Precondition: tys1 and tys2 are the same length, hence "OK"-canDecomposableTyConAppOK ev eq_rel tc tys1 tys2- = ASSERT( tys1 `equalLength` tys2 )- do { traceTcS "canDecomposableTyConAppOK"- (ppr ev $$ ppr eq_rel $$ ppr tc $$ ppr tys1 $$ ppr tys2)- ; case ev of- CtDerived {}- -> unifyDeriveds loc tc_roles tys1 tys2-- CtWanted { ctev_dest = dest }- -- new_locs and tc_roles are both infinite, so- -- we are guaranteed that cos has the same length- -- as tys1 and tys2- -> do { cos <- zipWith4M unifyWanted new_locs tc_roles tys1 tys2- ; setWantedEq dest (mkTyConAppCo role tc cos) }-- CtGiven { ctev_evar = evar }- -> do { let ev_co = mkCoVarCo evar- ; given_evs <- newGivenEvVars loc $- [ ( mkPrimEqPredRole r ty1 ty2- , evCoercion $ mkNthCo r i ev_co )- | (r, ty1, ty2, i) <- zip4 tc_roles tys1 tys2 [0..]- , r /= Phantom- , not (isCoercionTy ty1) && not (isCoercionTy ty2) ]- ; emitWorkNC given_evs }-- ; stopWith ev "Decomposed TyConApp" }-- where- loc = ctEvLoc ev- role = eqRelRole eq_rel-- -- infinite, as tyConRolesX returns an infinite tail of Nominal- tc_roles = tyConRolesX role tc-- -- Add nuances to the location during decomposition:- -- * if the argument is a kind argument, remember this, so that error- -- messages say "kind", not "type". This is determined based on whether- -- the corresponding tyConBinder is named (that is, dependent)- -- * if the argument is invisible, note this as well, again by- -- looking at the corresponding binder- -- For oversaturated tycons, we need the (repeat loc) tail, which doesn't- -- do either of these changes. (Forgetting to do so led to #16188)- --- -- NB: infinite in length- new_locs = [ new_loc- | bndr <- tyConBinders tc- , let new_loc0 | isNamedTyConBinder bndr = toKindLoc loc- | otherwise = loc- new_loc | isVisibleTyConBinder bndr- = updateCtLocOrigin new_loc0 toInvisibleOrigin- | otherwise- = new_loc0 ]- ++ repeat loc---- | Call when canonicalizing an equality fails, but if the equality is--- representational, there is some hope for the future.--- Examples in Note [Use canEqFailure in canDecomposableTyConApp]-canEqFailure :: CtEvidence -> EqRel- -> TcType -> TcType -> TcS (StopOrContinue Ct)-canEqFailure ev NomEq ty1 ty2- = canEqHardFailure ev ty1 ty2-canEqFailure ev ReprEq ty1 ty2- = do { (xi1, co1) <- flatten FM_FlattenAll ev ty1- ; (xi2, co2) <- flatten FM_FlattenAll ev ty2- -- We must flatten the types before putting them in the- -- inert set, so that we are sure to kick them out when- -- new equalities become available- ; traceTcS "canEqFailure with ReprEq" $- vcat [ ppr ev, ppr ty1, ppr ty2, ppr xi1, ppr xi2 ]- ; new_ev <- rewriteEqEvidence ev NotSwapped xi1 xi2 co1 co2- ; continueWith (mkIrredCt OtherCIS new_ev) }---- | Call when canonicalizing an equality fails with utterly no hope.-canEqHardFailure :: CtEvidence- -> TcType -> TcType -> TcS (StopOrContinue Ct)--- See Note [Make sure that insolubles are fully rewritten]-canEqHardFailure ev ty1 ty2- = do { traceTcS "canEqHardFailure" (ppr ty1 $$ ppr ty2)- ; (s1, co1) <- flatten FM_SubstOnly ev ty1- ; (s2, co2) <- flatten FM_SubstOnly ev ty2- ; new_ev <- rewriteEqEvidence ev NotSwapped s1 s2 co1 co2- ; continueWith (mkIrredCt InsolubleCIS new_ev) }--{--Note [Decomposing TyConApps]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-If we see (T s1 t1 ~ T s2 t2), then we can just decompose to- (s1 ~ s2, t1 ~ t2)-and push those back into the work list. But if- s1 = K k1 s2 = K k2-then we will just decomopose s1~s2, and it might be better to-do so on the spot. An important special case is where s1=s2,-and we get just Refl.--So canDecomposableTyCon is a fast-path decomposition that uses-unifyWanted etc to short-cut that work.--Note [Canonicalising type applications]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Given (s1 t1) ~ ty2, how should we proceed?-The simple things is to see if ty2 is of form (s2 t2), and-decompose. By this time s1 and s2 can't be saturated type-function applications, because those have been dealt with-by an earlier equation in can_eq_nc, so it is always sound to-decompose.--However, over-eager decomposition gives bad error messages-for things like- a b ~ Maybe c- e f ~ p -> q-Suppose (in the first example) we already know a~Array. Then if we-decompose the application eagerly, yielding- a ~ Maybe- b ~ c-we get an error "Can't match Array ~ Maybe",-but we'd prefer to get "Can't match Array b ~ Maybe c".--So instead can_eq_wanted_app flattens the LHS and RHS, in the hope of-replacing (a b) by (Array b), before using try_decompose_app to-decompose it.--Note [Make sure that insolubles are fully rewritten]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When an equality fails, we still want to rewrite the equality-all the way down, so that it accurately reflects- (a) the mutable reference substitution in force at start of solving- (b) any ty-binds in force at this point in solving-See Note [Rewrite insolubles] in GHC.Tc.Solver.Monad.-And if we don't do this there is a bad danger that-GHC.Tc.Solver.applyTyVarDefaulting will find a variable-that has in fact been substituted.--Note [Do not decompose Given polytype equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider [G] (forall a. t1 ~ forall a. t2). Can we decompose this?-No -- what would the evidence look like? So instead we simply discard-this given evidence.---Note [Combining insoluble constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-As this point we have an insoluble constraint, like Int~Bool.-- * If it is Wanted, delete it from the cache, so that subsequent- Int~Bool constraints give rise to separate error messages-- * But if it is Derived, DO NOT delete from cache. A class constraint- may get kicked out of the inert set, and then have its functional- dependency Derived constraints generated a second time. In that- case we don't want to get two (or more) error messages by- generating two (or more) insoluble fundep constraints from the same- class constraint.--Note [No top-level newtypes on RHS of representational equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we're in this situation:-- work item: [W] c1 : a ~R b- inert: [G] c2 : b ~R Id a--where- newtype Id a = Id a--We want to make sure canEqTyVar sees [W] a ~R a, after b is flattened-and the Id newtype is unwrapped. This is assured by requiring only flat-types in canEqTyVar *and* having the newtype-unwrapping check above-the tyvar check in can_eq_nc.--Note [Occurs check error]-~~~~~~~~~~~~~~~~~~~~~~~~~-If we have an occurs check error, are we necessarily hosed? Say our-tyvar is tv1 and the type it appears in is xi2. Because xi2 is function-free, then if we're computing w.r.t. nominal equality, then, yes, we're-hosed. Nothing good can come from (a ~ [a]). If we're computing w.r.t.-representational equality, this is a little subtler. Once again, (a ~R [a])-is a bad thing, but (a ~R N a) for a newtype N might be just fine. This-means also that (a ~ b a) might be fine, because `b` might become a newtype.--So, we must check: does tv1 appear in xi2 under any type constructor-that is generative w.r.t. representational equality? That's what-isInsolubleOccursCheck does.--See also #10715, which induced this addition.--Note [canCFunEqCan]-~~~~~~~~~~~~~~~~~~~-Flattening the arguments to a type family can change the kind of the type-family application. As an easy example, consider (Any k) where (k ~ Type)-is in the inert set. The original (Any k :: k) becomes (Any Type :: Type).-The problem here is that the fsk in the CFunEqCan will have the old kind.--The solution is to come up with a new fsk/fmv of the right kind. For-givens, this is easy: just introduce a new fsk and update the flat-cache-with the new one. For wanteds, we want to solve the old one if favor of-the new one, so we use dischargeFmv. This also kicks out constraints-from the inert set; this behavior is correct, as the kind-change may-allow more constraints to be solved.--We use `isTcReflexiveCo`, to ensure that we only use the hetero-kinded case-if we really need to. Of course `flattenArgsNom` should return `Refl`-whenever possible, but #15577 was an infinite loop because even-though the coercion was homo-kinded, `kind_co` was not `Refl`, so we-made a new (identical) CFunEqCan, and then the entire process repeated.--}--canCFunEqCan :: CtEvidence- -> TyCon -> [TcType] -- LHS- -> TcTyVar -- RHS- -> TcS (StopOrContinue Ct)--- ^ Canonicalise a CFunEqCan. We know that--- the arg types are already flat,--- and the RHS is a fsk, which we must *not* substitute.--- So just substitute in the LHS-canCFunEqCan ev fn tys fsk- = do { (tys', cos, kind_co) <- flattenArgsNom ev fn tys- -- cos :: tys' ~ tys-- ; let lhs_co = mkTcTyConAppCo Nominal fn cos- -- :: F tys' ~ F tys- new_lhs = mkTyConApp fn tys'-- flav = ctEvFlavour ev- ; (ev', fsk')- <- if isTcReflexiveCo kind_co -- See Note [canCFunEqCan]- then do { traceTcS "canCFunEqCan: refl" (ppr new_lhs)- ; let fsk_ty = mkTyVarTy fsk- ; ev' <- rewriteEqEvidence ev NotSwapped new_lhs fsk_ty- lhs_co (mkTcNomReflCo fsk_ty)- ; return (ev', fsk) }- else do { traceTcS "canCFunEqCan: non-refl" $- vcat [ text "Kind co:" <+> ppr kind_co- , text "RHS:" <+> ppr fsk <+> dcolon <+> ppr (tyVarKind fsk)- , text "LHS:" <+> hang (ppr (mkTyConApp fn tys))- 2 (dcolon <+> ppr (tcTypeKind (mkTyConApp fn tys)))- , text "New LHS" <+> hang (ppr new_lhs)- 2 (dcolon <+> ppr (tcTypeKind new_lhs)) ]- ; (ev', new_co, new_fsk)- <- newFlattenSkolem flav (ctEvLoc ev) fn tys'- ; let xi = mkTyVarTy new_fsk `mkCastTy` kind_co- -- sym lhs_co :: F tys ~ F tys'- -- new_co :: F tys' ~ new_fsk- -- co :: F tys ~ (new_fsk |> kind_co)- co = mkTcSymCo lhs_co `mkTcTransCo`- mkTcCoherenceRightCo Nominal- (mkTyVarTy new_fsk)- kind_co- new_co-- ; traceTcS "Discharging fmv/fsk due to hetero flattening" (ppr ev)- ; dischargeFunEq ev fsk co xi- ; return (ev', new_fsk) }-- ; extendFlatCache fn tys' (ctEvCoercion ev', mkTyVarTy fsk', ctEvFlavour ev')- ; continueWith (CFunEqCan { cc_ev = ev', cc_fun = fn- , cc_tyargs = tys', cc_fsk = fsk' }) }------------------------canEqTyVar :: CtEvidence -- ev :: lhs ~ rhs- -> EqRel -> SwapFlag- -> TcTyVar -- tv1- -> TcType -- lhs: pretty lhs, already flat- -> TcType -> TcType -- rhs: already flat- -> TcS (StopOrContinue Ct)-canEqTyVar ev eq_rel swapped tv1 ps_xi1 xi2 ps_xi2- | k1 `tcEqType` k2- = canEqTyVarHomo ev eq_rel swapped tv1 ps_xi1 xi2 ps_xi2-- | otherwise- = canEqTyVarHetero ev eq_rel swapped tv1 ps_xi1 k1 xi2 ps_xi2 k2-- where- k1 = tyVarKind tv1- k2 = tcTypeKind xi2--canEqTyVarHetero :: CtEvidence -- :: (tv1 :: ki1) ~ (xi2 :: ki2)- -> EqRel -> SwapFlag- -> TcTyVar -> TcType -- tv1, pretty tv1- -> TcKind -- ki1- -> TcType -> TcType -- xi2, pretty xi2 :: ki2- -> TcKind -- ki2- -> TcS (StopOrContinue Ct)-canEqTyVarHetero ev eq_rel swapped tv1 ps_tv1 ki1 xi2 ps_xi2 ki2- -- See Note [Equalities with incompatible kinds]- = do { kind_co <- emit_kind_co -- :: ki2 ~N ki1-- ; let -- kind_co :: (ki2 :: *) ~N (ki1 :: *) (whether swapped or not)- -- co1 :: kind(tv1) ~N ki1- rhs' = xi2 `mkCastTy` kind_co -- :: ki1- ps_rhs' = ps_xi2 `mkCastTy` kind_co -- :: ki1- rhs_co = mkTcGReflLeftCo role xi2 kind_co- -- rhs_co :: (xi2 |> kind_co) ~ xi2-- lhs' = mkTyVarTy tv1 -- same as old lhs- lhs_co = mkTcReflCo role lhs'-- ; traceTcS "Hetero equality gives rise to kind equality"- (ppr kind_co <+> dcolon <+> sep [ ppr ki2, text "~#", ppr ki1 ])- ; type_ev <- rewriteEqEvidence ev swapped lhs' rhs' lhs_co rhs_co-- -- rewriteEqEvidence carries out the swap, so we're NotSwapped any more- ; canEqTyVarHomo type_ev eq_rel NotSwapped tv1 ps_tv1 rhs' ps_rhs' }- where- emit_kind_co :: TcS CoercionN- emit_kind_co- | CtGiven { ctev_evar = evar } <- ev- = do { let kind_co = maybe_sym $ mkTcKindCo (mkTcCoVarCo evar) -- :: k2 ~ k1- ; kind_ev <- newGivenEvVar kind_loc (kind_pty, evCoercion kind_co)- ; emitWorkNC [kind_ev]- ; return (ctEvCoercion kind_ev) }-- | otherwise- = unifyWanted kind_loc Nominal ki2 ki1-- loc = ctev_loc ev- role = eqRelRole eq_rel- kind_loc = mkKindLoc (mkTyVarTy tv1) xi2 loc- kind_pty = mkHeteroPrimEqPred liftedTypeKind liftedTypeKind ki2 ki1-- maybe_sym = case swapped of- IsSwapped -> id -- if the input is swapped, then we already- -- will have k2 ~ k1- NotSwapped -> mkTcSymCo---- guaranteed that tcTypeKind lhs == tcTypeKind rhs-canEqTyVarHomo :: CtEvidence- -> EqRel -> SwapFlag- -> TcTyVar -- lhs: tv1- -> TcType -- pretty lhs, flat- -> TcType -> TcType -- rhs, flat- -> TcS (StopOrContinue Ct)-canEqTyVarHomo ev eq_rel swapped tv1 ps_xi1 xi2 _- | Just (tv2, _) <- tcGetCastedTyVar_maybe xi2- , tv1 == tv2- = canEqReflexive ev eq_rel (mkTyVarTy tv1)- -- we don't need to check co because it must be reflexive-- -- this guarantees (TyEq:TV)- | Just (tv2, co2) <- tcGetCastedTyVar_maybe xi2- , swapOverTyVars (isGiven ev) tv1 tv2- = do { traceTcS "canEqTyVar swapOver" (ppr tv1 $$ ppr tv2 $$ ppr swapped)- ; let role = eqRelRole eq_rel- sym_co2 = mkTcSymCo co2- ty1 = mkTyVarTy tv1- new_lhs = ty1 `mkCastTy` sym_co2- lhs_co = mkTcGReflLeftCo role ty1 sym_co2-- new_rhs = mkTyVarTy tv2- rhs_co = mkTcGReflRightCo role new_rhs co2-- ; new_ev <- rewriteEqEvidence ev swapped new_lhs new_rhs lhs_co rhs_co-- ; dflags <- getDynFlags- ; canEqTyVar2 dflags new_ev eq_rel IsSwapped tv2 (ps_xi1 `mkCastTy` sym_co2) }--canEqTyVarHomo ev eq_rel swapped tv1 _ _ ps_xi2- = do { dflags <- getDynFlags- ; canEqTyVar2 dflags ev eq_rel swapped tv1 ps_xi2 }---- The RHS here is either not a casted tyvar, or it's a tyvar but we want--- to rewrite the LHS to the RHS (as per swapOverTyVars)-canEqTyVar2 :: DynFlags- -> CtEvidence -- lhs ~ rhs (or, if swapped, orhs ~ olhs)- -> EqRel- -> SwapFlag- -> TcTyVar -- lhs = tv, flat- -> TcType -- rhs, flat- -> TcS (StopOrContinue Ct)--- LHS is an inert type variable,--- and RHS is fully rewritten, but with type synonyms--- preserved as much as possible--- guaranteed that tyVarKind lhs == typeKind rhs, for (TyEq:K)--- the "flat" requirement guarantees (TyEq:AFF)--- (TyEq:N) is checked in can_eq_nc', and (TyEq:TV) is handled in canEqTyVarHomo-canEqTyVar2 dflags ev eq_rel swapped tv1 rhs- -- this next line checks also for coercion holes; see- -- Note [Equalities with incompatible kinds]- | MTVU_OK rhs' <- mtvu -- No occurs check- -- Must do the occurs check even on tyvar/tyvar- -- equalities, in case have x ~ (y :: ..x...)- -- #12593- -- guarantees (TyEq:OC), (TyEq:F), and (TyEq:H)- = do { new_ev <- rewriteEqEvidence ev swapped lhs rhs' rewrite_co1 rewrite_co2- ; continueWith (CTyEqCan { cc_ev = new_ev, cc_tyvar = tv1- , cc_rhs = rhs', cc_eq_rel = eq_rel }) }-- | otherwise -- For some reason (occurs check, or forall) we can't unify- -- We must not use it for further rewriting!- = do { traceTcS "canEqTyVar2 can't unify" (ppr tv1 $$ ppr rhs $$ ppr mtvu)- ; new_ev <- rewriteEqEvidence ev swapped lhs rhs rewrite_co1 rewrite_co2- ; let status | isInsolubleOccursCheck eq_rel tv1 rhs- = InsolubleCIS- -- If we have a ~ [a], it is not canonical, and in particular- -- we don't want to rewrite existing inerts with it, otherwise- -- we'd risk divergence in the constraint solver-- | MTVU_HoleBlocker <- mtvu- = BlockedCIS- -- This is the case detailed in- -- Note [Equalities with incompatible kinds]-- | otherwise- = OtherCIS- -- A representational equality with an occurs-check problem isn't- -- insoluble! For example:- -- a ~R b a- -- We might learn that b is the newtype Id.- -- But, the occurs-check certainly prevents the equality from being- -- canonical, and we might loop if we were to use it in rewriting.-- ; continueWith (mkIrredCt status new_ev) }- where- mtvu = metaTyVarUpdateOK dflags tv1 rhs- -- Despite the name of the function, tv1 may not be a- -- unification variable; we are really checking that this- -- equality is ok to be used to rewrite others, i.e. that- -- it satisfies the conditions for CTyEqCan-- role = eqRelRole eq_rel-- lhs = mkTyVarTy tv1-- rewrite_co1 = mkTcReflCo role lhs- rewrite_co2 = mkTcReflCo role rhs---- | Solve a reflexive equality constraint-canEqReflexive :: CtEvidence -- ty ~ ty- -> EqRel- -> TcType -- ty- -> TcS (StopOrContinue Ct) -- always Stop-canEqReflexive ev eq_rel ty- = do { setEvBindIfWanted ev (evCoercion $- mkTcReflCo (eqRelRole eq_rel) ty)- ; stopWith ev "Solved by reflexivity" }--{- Note [Equalities with incompatible kinds]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-What do we do when we have an equality-- (tv :: k1) ~ (rhs :: k2)--where k1 and k2 differ? Easy: we create a coercion that relates k1 and-k2 and use this to cast. To wit, from-- [X] (tv :: k1) ~ (rhs :: k2)--(where [X] is [G], [W], or [D]), we go to-- [noDerived X] co :: k2 ~ k1- [X] (tv :: k1) ~ ((rhs |> co) :: k1)--where-- noDerived G = G- noDerived _ = W--For Wanted/Derived, the [X] constraint is "blocked" (not CTyEqCan, is CIrred)-until the k1~k2 constraint solved: Wrinkle (2).--Wrinkles:-- (1) The noDerived step is because Derived equalities have no evidence.- And yet we absolutely need evidence to be able to proceed here.- Given evidence will use the KindCo coercion; Wanted evidence will- be a coercion hole. Even a Derived hetero equality begets a Wanted- kind equality.-- (2) Though it would be sound to do so, we must not mark the rewritten Wanted- [W] (tv :: k1) ~ ((rhs |> co) :: k1)- as canonical in the inert set. In particular, we must not unify tv.- If we did, the Wanted becomes a Given (effectively), and then can- rewrite other Wanteds. But that's bad: See Note [Wanteds do not rewrite Wanteds]- in GHC.Tc.Types.Constraint. The problem is about poor error messages. See #11198 for- tales of destruction.-- So, we have an invariant on CTyEqCan (TyEq:H) that the RHS does not have- any coercion holes. This is checked in metaTyVarUpdateOK. We also- must be sure to kick out any constraints that mention coercion holes- when those holes get filled in.-- (2a) We don't want to do this for CoercionHoles that witness- CFunEqCans (that are produced by the flattener), as these will disappear- once we unflatten. So we remember in the CoercionHole structure- whether the presence of the hole should block substitution or not.- A bit gross, this.-- (2b) We must now absolutely make sure to kick out any constraints that- mention a newly-filled-in coercion hole. This is done in- kickOutAfterFillingCoercionHole.-- (3) Suppose we have [W] (a :: k1) ~ (rhs :: k2). We duly follow the- algorithm detailed here, producing [W] co :: k2 ~ k1, and adding- [W] (a :: k1) ~ ((rhs |> co) :: k1) to the irreducibles. Some time- later, we solve co, and fill in co's coercion hole. This kicks out- the irreducible as described in (2b).- But now, during canonicalization, we see the cast- and remove it, in canEqCast. By the time we get into canEqTyVar, the equality- is heterogeneous again, and the process repeats.-- To avoid this, we don't strip casts off a type if the other type- in the equality is a tyvar. And this is an improvement regardless:- because tyvars can, generally, unify with casted types, there's no- reason to go through the work of stripping off the cast when the- cast appears opposite a tyvar. This is implemented in the cast case- of can_eq_nc'.-- (4) Reporting an error for a constraint that is blocked only because- of wrinkle (2) is hard: what would we say to users? And we don't- really need to report, because if a constraint is blocked, then- there is unsolved wanted blocking it; that unsolved wanted will- be reported. We thus push such errors to the bottom of the queue- in the error-reporting code; they should never be printed.-- (4a) It would seem possible to do this filtering just based on the- presence of a blocking coercion hole. However, this is no good,- as it suppresses e.g. no-instance-found errors. We thus record- a CtIrredStatus in CIrredCan and filter based on this status.- This happened in T14584. An alternative approach is to expressly- look for *equalities* with blocking coercion holes, but actually- recording the blockage in a status field seems nicer.-- (4b) The error message might be printed with -fdefer-type-errors,- so it still must exist. This is the only reason why there is- a message at all. Otherwise, we could simply do nothing.--Historical note:--We used to do this via emitting a Derived kind equality and then parking-the heterogeneous equality as irreducible. But this new approach is much-more direct. And it doesn't produce duplicate Deriveds (as the old one did).--Note [Type synonyms and canonicalization]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We treat type synonym applications as xi types, that is, they do not-count as type function applications. However, we do need to be a bit-careful with type synonyms: like type functions they may not be-generative or injective. However, unlike type functions, they are-parametric, so there is no problem in expanding them whenever we see-them, since we do not need to know anything about their arguments in-order to expand them; this is what justifies not having to treat them-as specially as type function applications. The thing that causes-some subtleties is that we prefer to leave type synonym applications-*unexpanded* whenever possible, in order to generate better error-messages.--If we encounter an equality constraint with type synonym applications-on both sides, or a type synonym application on one side and some sort-of type application on the other, we simply must expand out the type-synonyms in order to continue decomposing the equality constraint into-primitive equality constraints. For example, suppose we have-- type F a = [Int]--and we encounter the equality-- F a ~ [b]--In order to continue we must expand F a into [Int], giving us the-equality-- [Int] ~ [b]--which we can then decompose into the more primitive equality-constraint-- Int ~ b.--However, if we encounter an equality constraint with a type synonym-application on one side and a variable on the other side, we should-NOT (necessarily) expand the type synonym, since for the purpose of-good error messages we want to leave type synonyms unexpanded as much-as possible. Hence the ps_xi1, ps_xi2 argument passed to canEqTyVar.---}--{--************************************************************************-* *- Evidence transformation-* *-************************************************************************--}--data StopOrContinue a- = ContinueWith a -- The constraint was not solved, although it may have- -- been rewritten-- | Stop CtEvidence -- The (rewritten) constraint was solved- SDoc -- Tells how it was solved- -- Any new sub-goals have been put on the work list- deriving (Functor)--instance Outputable a => Outputable (StopOrContinue a) where- ppr (Stop ev s) = text "Stop" <> parens s <+> ppr ev- ppr (ContinueWith w) = text "ContinueWith" <+> ppr w--continueWith :: a -> TcS (StopOrContinue a)-continueWith = return . ContinueWith--stopWith :: CtEvidence -> String -> TcS (StopOrContinue a)-stopWith ev s = return (Stop ev (text s))--andWhenContinue :: TcS (StopOrContinue a)- -> (a -> TcS (StopOrContinue b))- -> TcS (StopOrContinue b)-andWhenContinue tcs1 tcs2- = do { r <- tcs1- ; case r of- Stop ev s -> return (Stop ev s)- ContinueWith ct -> tcs2 ct }-infixr 0 `andWhenContinue` -- allow chaining with ($)--rewriteEvidence :: CtEvidence -- old evidence- -> TcPredType -- new predicate- -> TcCoercion -- Of type :: new predicate ~ <type of old evidence>- -> TcS (StopOrContinue CtEvidence)--- Returns Just new_ev iff either (i) 'co' is reflexivity--- or (ii) 'co' is not reflexivity, and 'new_pred' not cached--- In either case, there is nothing new to do with new_ev-{-- rewriteEvidence old_ev new_pred co-Main purpose: create new evidence for new_pred;- unless new_pred is cached already-* Returns a new_ev : new_pred, with same wanted/given/derived flag as old_ev-* If old_ev was wanted, create a binding for old_ev, in terms of new_ev-* If old_ev was given, AND not cached, create a binding for new_ev, in terms of old_ev-* Returns Nothing if new_ev is already cached-- Old evidence New predicate is Return new evidence- flavour of same flavor- -------------------------------------------------------------------- Wanted Already solved or in inert Nothing- or Derived Not Just new_evidence-- Given Already in inert Nothing- Not Just new_evidence--Note [Rewriting with Refl]-~~~~~~~~~~~~~~~~~~~~~~~~~~-If the coercion is just reflexivity then you may re-use the same-variable. But be careful! Although the coercion is Refl, new_pred-may reflect the result of unification alpha := ty, so new_pred might-not _look_ the same as old_pred, and it's vital to proceed from now on-using new_pred.--qThe flattener preserves type synonyms, so they should appear in new_pred-as well as in old_pred; that is important for good error messages.- -}---rewriteEvidence old_ev@(CtDerived {}) new_pred _co- = -- If derived, don't even look at the coercion.- -- This is very important, DO NOT re-order the equations for- -- rewriteEvidence to put the isTcReflCo test first!- -- Why? Because for *Derived* constraints, c, the coercion, which- -- was produced by flattening, may contain suspended calls to- -- (ctEvExpr c), which fails for Derived constraints.- -- (Getting this wrong caused #7384.)- continueWith (old_ev { ctev_pred = new_pred })--rewriteEvidence old_ev new_pred co- | isTcReflCo co -- See Note [Rewriting with Refl]- = continueWith (old_ev { ctev_pred = new_pred })--rewriteEvidence ev@(CtGiven { ctev_evar = old_evar, ctev_loc = loc }) new_pred co- = do { new_ev <- newGivenEvVar loc (new_pred, new_tm)- ; continueWith new_ev }- where- -- mkEvCast optimises ReflCo- new_tm = mkEvCast (evId old_evar) (tcDowngradeRole Representational- (ctEvRole ev)- (mkTcSymCo co))--rewriteEvidence ev@(CtWanted { ctev_dest = dest- , ctev_nosh = si- , ctev_loc = loc }) new_pred co- = do { mb_new_ev <- newWanted_SI si loc new_pred- -- The "_SI" variant ensures that we make a new Wanted- -- with the same shadow-info as the existing one- -- with the same shadow-info as the existing one (#16735)- ; MASSERT( tcCoercionRole co == ctEvRole ev )- ; setWantedEvTerm dest- (mkEvCast (getEvExpr mb_new_ev)- (tcDowngradeRole Representational (ctEvRole ev) co))- ; case mb_new_ev of- Fresh new_ev -> continueWith new_ev- Cached _ -> stopWith ev "Cached wanted" }---rewriteEqEvidence :: CtEvidence -- Old evidence :: olhs ~ orhs (not swapped)- -- or orhs ~ olhs (swapped)- -> SwapFlag- -> TcType -> TcType -- New predicate nlhs ~ nrhs- -> TcCoercion -- lhs_co, of type :: nlhs ~ olhs- -> TcCoercion -- rhs_co, of type :: nrhs ~ orhs- -> TcS CtEvidence -- Of type nlhs ~ nrhs--- For (rewriteEqEvidence (Given g olhs orhs) False nlhs nrhs lhs_co rhs_co)--- we generate--- If not swapped--- g1 : nlhs ~ nrhs = lhs_co ; g ; sym rhs_co--- If 'swapped'--- g1 : nlhs ~ nrhs = lhs_co ; Sym g ; sym rhs_co------ For (Wanted w) we do the dual thing.--- New w1 : nlhs ~ nrhs--- If not swapped--- w : olhs ~ orhs = sym lhs_co ; w1 ; rhs_co--- If swapped--- w : orhs ~ olhs = sym rhs_co ; sym w1 ; lhs_co------ It's all a form of rewwriteEvidence, specialised for equalities-rewriteEqEvidence old_ev swapped nlhs nrhs lhs_co rhs_co- | CtDerived {} <- old_ev -- Don't force the evidence for a Derived- = return (old_ev { ctev_pred = new_pred })-- | NotSwapped <- swapped- , isTcReflCo lhs_co -- See Note [Rewriting with Refl]- , isTcReflCo rhs_co- = return (old_ev { ctev_pred = new_pred })-- | CtGiven { ctev_evar = old_evar } <- old_ev- = do { let new_tm = evCoercion (lhs_co- `mkTcTransCo` maybeSym swapped (mkTcCoVarCo old_evar)- `mkTcTransCo` mkTcSymCo rhs_co)- ; newGivenEvVar loc' (new_pred, new_tm) }-- | CtWanted { ctev_dest = dest, ctev_nosh = si } <- old_ev- = case dest of- HoleDest hole ->- do { (new_ev, hole_co) <- newWantedEq_SI (ch_blocker hole) si loc'- (ctEvRole old_ev) nlhs nrhs- -- The "_SI" variant ensures that we make a new Wanted- -- with the same shadow-info as the existing one (#16735)- ; let co = maybeSym swapped $- mkSymCo lhs_co- `mkTransCo` hole_co- `mkTransCo` rhs_co- ; setWantedEq dest co- ; traceTcS "rewriteEqEvidence" (vcat [ppr old_ev, ppr nlhs, ppr nrhs, ppr co])- ; return new_ev }-- _ -> panic "rewriteEqEvidence"--#if __GLASGOW_HASKELL__ <= 810- | otherwise- = panic "rewriteEvidence"-#endif- where- new_pred = mkTcEqPredLikeEv old_ev nlhs nrhs-- -- equality is like a type class. Bumping the depth is necessary because- -- of recursive newtypes, where "reducing" a newtype can actually make- -- it bigger. See Note [Newtypes can blow the stack].- loc = ctEvLoc old_ev- loc' = bumpCtLocDepth loc--{- Note [unifyWanted and unifyDerived]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When decomposing equalities we often create new wanted constraints for-(s ~ t). But what if s=t? Then it'd be faster to return Refl right away.-Similar remarks apply for Derived.--Rather than making an equality test (which traverses the structure of the-type, perhaps fruitlessly), unifyWanted traverses the common structure, and-bales out when it finds a difference by creating a new Wanted constraint.-But where it succeeds in finding common structure, it just builds a coercion-to reflect it.--}--unifyWanted :: CtLoc -> Role- -> TcType -> TcType -> TcS Coercion--- Return coercion witnessing the equality of the two types,--- emitting new work equalities where necessary to achieve that--- Very good short-cut when the two types are equal, or nearly so--- See Note [unifyWanted and unifyDerived]--- The returned coercion's role matches the input parameter-unifyWanted loc Phantom ty1 ty2- = do { kind_co <- unifyWanted loc Nominal (tcTypeKind ty1) (tcTypeKind ty2)- ; return (mkPhantomCo kind_co ty1 ty2) }--unifyWanted loc role orig_ty1 orig_ty2- = go orig_ty1 orig_ty2- where- go ty1 ty2 | Just ty1' <- tcView ty1 = go ty1' ty2- go ty1 ty2 | Just ty2' <- tcView ty2 = go ty1 ty2'-- go (FunTy _ w1 s1 t1) (FunTy _ w2 s2 t2)- = do { co_s <- unifyWanted loc role s1 s2- ; co_t <- unifyWanted loc role t1 t2- ; co_w <- unifyWanted loc Nominal w1 w2- ; return (mkFunCo role co_w co_s co_t) }- go (TyConApp tc1 tys1) (TyConApp tc2 tys2)- | tc1 == tc2, tys1 `equalLength` tys2- , isInjectiveTyCon tc1 role -- don't look under newtypes at Rep equality- = do { cos <- zipWith3M (unifyWanted loc)- (tyConRolesX role tc1) tys1 tys2- ; return (mkTyConAppCo role tc1 cos) }-- go ty1@(TyVarTy tv) ty2- = do { mb_ty <- isFilledMetaTyVar_maybe tv- ; case mb_ty of- Just ty1' -> go ty1' ty2- Nothing -> bale_out ty1 ty2}- go ty1 ty2@(TyVarTy tv)- = do { mb_ty <- isFilledMetaTyVar_maybe tv- ; case mb_ty of- Just ty2' -> go ty1 ty2'- Nothing -> bale_out ty1 ty2 }-- go ty1@(CoercionTy {}) (CoercionTy {})- = return (mkReflCo role ty1) -- we just don't care about coercions!-- go ty1 ty2 = bale_out ty1 ty2-- bale_out ty1 ty2- | ty1 `tcEqType` ty2 = return (mkTcReflCo role ty1)- -- Check for equality; e.g. a ~ a, or (m a) ~ (m a)- | otherwise = emitNewWantedEq loc role orig_ty1 orig_ty2--unifyDeriveds :: CtLoc -> [Role] -> [TcType] -> [TcType] -> TcS ()--- See Note [unifyWanted and unifyDerived]-unifyDeriveds loc roles tys1 tys2 = zipWith3M_ (unify_derived loc) roles tys1 tys2--unifyDerived :: CtLoc -> Role -> Pair TcType -> TcS ()--- See Note [unifyWanted and unifyDerived]-unifyDerived loc role (Pair ty1 ty2) = unify_derived loc role ty1 ty2--unify_derived :: CtLoc -> Role -> TcType -> TcType -> TcS ()--- Create new Derived and put it in the work list--- Should do nothing if the two types are equal--- See Note [unifyWanted and unifyDerived]-unify_derived _ Phantom _ _ = return ()-unify_derived loc role orig_ty1 orig_ty2- = go orig_ty1 orig_ty2- where- go ty1 ty2 | Just ty1' <- tcView ty1 = go ty1' ty2- go ty1 ty2 | Just ty2' <- tcView ty2 = go ty1 ty2'-- go (FunTy _ w1 s1 t1) (FunTy _ w2 s2 t2)- = do { unify_derived loc role s1 s2- ; unify_derived loc role t1 t2- ; unify_derived loc Nominal w1 w2 }- go (TyConApp tc1 tys1) (TyConApp tc2 tys2)- | tc1 == tc2, tys1 `equalLength` tys2- , isInjectiveTyCon tc1 role- = unifyDeriveds loc (tyConRolesX role tc1) tys1 tys2- go ty1@(TyVarTy tv) ty2- = do { mb_ty <- isFilledMetaTyVar_maybe tv- ; case mb_ty of- Just ty1' -> go ty1' ty2- Nothing -> bale_out ty1 ty2 }- go ty1 ty2@(TyVarTy tv)- = do { mb_ty <- isFilledMetaTyVar_maybe tv- ; case mb_ty of- Just ty2' -> go ty1 ty2'- Nothing -> bale_out ty1 ty2 }- go ty1 ty2 = bale_out ty1 ty2-- bale_out ty1 ty2- | ty1 `tcEqType` ty2 = return ()- -- Check for equality; e.g. a ~ a, or (m a) ~ (m a)- | otherwise = emitNewDerivedEq loc role orig_ty1 orig_ty2--maybeSym :: SwapFlag -> TcCoercion -> TcCoercion-maybeSym IsSwapped co = mkTcSymCo co-maybeSym NotSwapped co = co+{-# LANGUAGE MultiWayIf #-}++module GHC.Tc.Solver.Canonical(+ canonicalize,+ unifyDerived, unifyTest, UnifyTestResult(..),+ makeSuperClasses,+ StopOrContinue(..), stopWith, continueWith, andWhenContinue,+ solveCallStack -- For GHC.Tc.Solver+ ) where++#include "GhclibHsVersions.h"++import GHC.Prelude++import GHC.Tc.Types.Constraint+import GHC.Core.Predicate+import GHC.Tc.Types.Origin+import GHC.Tc.Utils.Unify+import GHC.Tc.Utils.TcType+import GHC.Core.Type+import GHC.Tc.Solver.Rewrite+import GHC.Tc.Solver.Monad+import GHC.Tc.Types.Evidence+import GHC.Tc.Types.EvTerm+import GHC.Core.Class+import GHC.Core.TyCon+import GHC.Core.Multiplicity+import GHC.Core.TyCo.Rep -- cleverly decomposes types, good for completeness checking+import GHC.Core.Coercion+import GHC.Core.Coercion.Axiom+import GHC.Core+import GHC.Types.Id( mkTemplateLocals )+import GHC.Core.FamInstEnv ( FamInstEnvs )+import GHC.Tc.Instance.Family ( tcTopNormaliseNewTypeTF_maybe )+import GHC.Types.Var+import GHC.Types.Var.Env( mkInScopeSet )+import GHC.Types.Var.Set( delVarSetList, anyVarSet )+import GHC.Utils.Outputable+import GHC.Utils.Panic+import GHC.Builtin.Types ( anyTypeOfKind )+import GHC.Driver.Session( DynFlags )+import GHC.Types.Name.Set+import GHC.Types.Name.Reader+import GHC.Hs.Type( HsIPName(..) )++import GHC.Data.Pair+import GHC.Utils.Misc+import GHC.Data.Bag+import GHC.Utils.Monad+import Control.Monad+import Data.Maybe ( isJust, isNothing )+import Data.List ( zip4, partition )+import GHC.Types.Unique.Set( nonDetEltsUniqSet )+import GHC.Types.Basic++import Data.Bifunctor ( bimap )+import Data.Foldable ( traverse_ )++{-+************************************************************************+* *+* The Canonicaliser *+* *+************************************************************************++Note [Canonicalization]+~~~~~~~~~~~~~~~~~~~~~~~++Canonicalization converts a simple constraint to a canonical form. It is+unary (i.e. treats individual constraints one at a time).++Constraints originating from user-written code come into being as+CNonCanonicals. We know nothing about these constraints. So, first:++ Classify CNonCanoncal constraints, depending on whether they+ are equalities, class predicates, or other.++Then proceed depending on the shape of the constraint. Generally speaking,+each constraint gets rewritten and then decomposed into one of several forms+(see type Ct in GHC.Tc.Types).++When an already-canonicalized constraint gets kicked out of the inert set,+it must be recanonicalized. But we know a bit about its shape from the+last time through, so we can skip the classification step.++-}++-- Top-level canonicalization+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++canonicalize :: Ct -> TcS (StopOrContinue Ct)+canonicalize (CNonCanonical { cc_ev = ev })+ = {-# SCC "canNC" #-}+ canNC ev++canonicalize (CQuantCan (QCI { qci_ev = ev, qci_pend_sc = pend_sc }))+ = canForAll ev pend_sc++canonicalize (CIrredCan { cc_ev = ev })+ = canNC ev+ -- Instead of rewriting the evidence before classifying, it's possible we+ -- can make progress without the rewrite. Try this first.+ -- For insolubles (all of which are equalities), do /not/ rewrite the arguments+ -- In #14350 doing so led entire-unnecessary and ridiculously large+ -- type function expansion. Instead, canEqNC just applies+ -- the substitution to the predicate, and may do decomposition;+ -- e.g. a ~ [a], where [G] a ~ [Int], can decompose++canonicalize (CDictCan { cc_ev = ev, cc_class = cls+ , cc_tyargs = xis, cc_pend_sc = pend_sc })+ = {-# SCC "canClass" #-}+ canClass ev cls xis pend_sc++canonicalize (CEqCan { cc_ev = ev+ , cc_lhs = lhs+ , cc_rhs = rhs+ , cc_eq_rel = eq_rel })+ = {-# SCC "canEqLeafTyVarEq" #-}+ canEqNC ev eq_rel (canEqLHSType lhs) rhs++canNC :: CtEvidence -> TcS (StopOrContinue Ct)+canNC ev =+ case classifyPredType pred of+ ClassPred cls tys -> do traceTcS "canEvNC:cls" (ppr cls <+> ppr tys)+ canClassNC ev cls tys+ EqPred eq_rel ty1 ty2 -> do traceTcS "canEvNC:eq" (ppr ty1 $$ ppr ty2)+ canEqNC ev eq_rel ty1 ty2+ IrredPred {} -> do traceTcS "canEvNC:irred" (ppr pred)+ canIrred ev+ ForAllPred tvs th p -> do traceTcS "canEvNC:forall" (ppr pred)+ canForAllNC ev tvs th p+ where+ pred = ctEvPred ev++{-+************************************************************************+* *+* Class Canonicalization+* *+************************************************************************+-}++canClassNC :: CtEvidence -> Class -> [Type] -> TcS (StopOrContinue Ct)+-- "NC" means "non-canonical"; that is, we have got here+-- from a NonCanonical constraint, not from a CDictCan+-- Precondition: EvVar is class evidence+canClassNC ev cls tys+ | isGiven ev -- See Note [Eagerly expand given superclasses]+ = do { sc_cts <- mkStrictSuperClasses ev [] [] cls tys+ ; emitWork sc_cts+ ; canClass ev cls tys False }++ | isWanted ev+ , Just ip_name <- isCallStackPred cls tys+ , OccurrenceOf func <- ctLocOrigin loc+ -- If we're given a CallStack constraint that arose from a function+ -- call, we need to push the current call-site onto the stack instead+ -- of solving it directly from a given.+ -- See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence+ -- and Note [Solving CallStack constraints] in GHC.Tc.Solver.Monad+ = do { -- First we emit a new constraint that will capture the+ -- given CallStack.+ ; let new_loc = setCtLocOrigin loc (IPOccOrigin (HsIPName ip_name))+ -- We change the origin to IPOccOrigin so+ -- this rule does not fire again.+ -- See Note [Overview of implicit CallStacks]++ ; new_ev <- newWantedEvVarNC new_loc pred++ -- Then we solve the wanted by pushing the call-site+ -- onto the newly emitted CallStack+ ; let ev_cs = EvCsPushCall func (ctLocSpan loc) (ctEvExpr new_ev)+ ; solveCallStack ev ev_cs++ ; canClass new_ev cls tys False }++ | otherwise+ = canClass ev cls tys (has_scs cls)++ where+ has_scs cls = not (null (classSCTheta cls))+ loc = ctEvLoc ev+ pred = ctEvPred ev++solveCallStack :: CtEvidence -> EvCallStack -> TcS ()+-- Also called from GHC.Tc.Solver when defaulting call stacks+solveCallStack ev ev_cs = do+ -- We're given ev_cs :: CallStack, but the evidence term should be a+ -- dictionary, so we have to coerce ev_cs to a dictionary for+ -- `IP ip CallStack`. See Note [Overview of implicit CallStacks]+ cs_tm <- evCallStack ev_cs+ let ev_tm = mkEvCast cs_tm (wrapIP (ctEvPred ev))+ setEvBindIfWanted ev ev_tm++canClass :: CtEvidence+ -> Class -> [Type]+ -> Bool -- True <=> un-explored superclasses+ -> TcS (StopOrContinue Ct)+-- Precondition: EvVar is class evidence++canClass ev cls tys pend_sc+ = -- all classes do *nominal* matching+ ASSERT2( ctEvRole ev == Nominal, ppr ev $$ ppr cls $$ ppr tys )+ do { (xis, cos) <- rewriteArgsNom ev cls_tc tys+ ; let co = mkTcTyConAppCo Nominal cls_tc cos+ xi = mkClassPred cls xis+ mk_ct new_ev = CDictCan { cc_ev = new_ev+ , cc_tyargs = xis+ , cc_class = cls+ , cc_pend_sc = pend_sc }+ ; mb <- rewriteEvidence ev xi co+ ; traceTcS "canClass" (vcat [ ppr ev+ , ppr xi, ppr mb ])+ ; return (fmap mk_ct mb) }+ where+ cls_tc = classTyCon cls++{- Note [The superclass story]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We need to add superclass constraints for two reasons:++* For givens [G], they give us a route to proof. E.g.+ f :: Ord a => a -> Bool+ f x = x == x+ We get a Wanted (Eq a), which can only be solved from the superclass+ of the Given (Ord a).++* For wanteds [W], and deriveds [WD], [D], they may give useful+ functional dependencies. E.g.+ class C a b | a -> b where ...+ class C a b => D a b where ...+ Now a [W] constraint (D Int beta) has (C Int beta) as a superclass+ and that might tell us about beta, via C's fundeps. We can get this+ by generating a [D] (C Int beta) constraint. It's derived because+ we don't actually have to cough up any evidence for it; it's only there+ to generate fundep equalities.++See Note [Why adding superclasses can help].++For these reasons we want to generate superclass constraints for both+Givens and Wanteds. But:++* (Minor) they are often not needed, so generating them aggressively+ is a waste of time.++* (Major) if we want recursive superclasses, there would be an infinite+ number of them. Here is a real-life example (#10318);++ class (Frac (Frac a) ~ Frac a,+ Fractional (Frac a),+ IntegralDomain (Frac a))+ => IntegralDomain a where+ type Frac a :: *++ Notice that IntegralDomain has an associated type Frac, and one+ of IntegralDomain's superclasses is another IntegralDomain constraint.++So here's the plan:++1. Eagerly generate superclasses for given (but not wanted)+ constraints; see Note [Eagerly expand given superclasses].+ This is done using mkStrictSuperClasses in canClassNC, when+ we take a non-canonical Given constraint and cannonicalise it.++ However stop if you encounter the same class twice. That is,+ mkStrictSuperClasses expands eagerly, but has a conservative+ termination condition: see Note [Expanding superclasses] in GHC.Tc.Utils.TcType.++2. Solve the wanteds as usual, but do no further expansion of+ superclasses for canonical CDictCans in solveSimpleGivens or+ solveSimpleWanteds; Note [Danger of adding superclasses during solving]++ However, /do/ continue to eagerly expand superclasses for new /given/+ /non-canonical/ constraints (canClassNC does this). As #12175+ showed, a type-family application can expand to a class constraint,+ and we want to see its superclasses for just the same reason as+ Note [Eagerly expand given superclasses].++3. If we have any remaining unsolved wanteds+ (see Note [When superclasses help] in GHC.Tc.Types.Constraint)+ try harder: take both the Givens and Wanteds, and expand+ superclasses again. See the calls to expandSuperClasses in+ GHC.Tc.Solver.simpl_loop and solveWanteds.++ This may succeed in generating (a finite number of) extra Givens,+ and extra Deriveds. Both may help the proof.++3a An important wrinkle: only expand Givens from the current level.+ Two reasons:+ - We only want to expand it once, and that is best done at+ the level it is bound, rather than repeatedly at the leaves+ of the implication tree+ - We may be inside a type where we can't create term-level+ evidence anyway, so we can't superclass-expand, say,+ (a ~ b) to get (a ~# b). This happened in #15290.++4. Go round to (2) again. This loop (2,3,4) is implemented+ in GHC.Tc.Solver.simpl_loop.++The cc_pend_sc flag in a CDictCan records whether the superclasses of+this constraint have been expanded. Specifically, in Step 3 we only+expand superclasses for constraints with cc_pend_sc set to true (i.e.+isPendingScDict holds).++Why do we do this? Two reasons:++* To avoid repeated work, by repeatedly expanding the superclasses of+ same constraint,++* To terminate the above loop, at least in the -XNoRecursiveSuperClasses+ case. If there are recursive superclasses we could, in principle,+ expand forever, always encountering new constraints.++When we take a CNonCanonical or CIrredCan, but end up classifying it+as a CDictCan, we set the cc_pend_sc flag to False.++Note [Superclass loops]+~~~~~~~~~~~~~~~~~~~~~~~+Suppose we have+ class C a => D a+ class D a => C a++Then, when we expand superclasses, we'll get back to the self-same+predicate, so we have reached a fixpoint in expansion and there is no+point in fruitlessly expanding further. This case just falls out from+our strategy. Consider+ f :: C a => a -> Bool+ f x = x==x+Then canClassNC gets the [G] d1: C a constraint, and eager emits superclasses+G] d2: D a, [G] d3: C a (psc). (The "psc" means it has its sc_pend flag set.)+When processing d3 we find a match with d1 in the inert set, and we always+keep the inert item (d1) if possible: see Note [Replacement vs keeping] in+GHC.Tc.Solver.Interact. So d3 dies a quick, happy death.++Note [Eagerly expand given superclasses]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In step (1) of Note [The superclass story], why do we eagerly expand+Given superclasses by one layer? (By "one layer" we mean expand transitively+until you meet the same class again -- the conservative criterion embodied+in expandSuperClasses. So a "layer" might be a whole stack of superclasses.)+We do this eagerly for Givens mainly because of some very obscure+cases like this:++ instance Bad a => Eq (T a)++ f :: (Ord (T a)) => blah+ f x = ....needs Eq (T a), Ord (T a)....++Here if we can't satisfy (Eq (T a)) from the givens we'll use the+instance declaration; but then we are stuck with (Bad a). Sigh.+This is really a case of non-confluent proofs, but to stop our users+complaining we expand one layer in advance.++Note [Instance and Given overlap] in GHC.Tc.Solver.Interact.++We also want to do this if we have++ f :: F (T a) => blah++where+ type instance F (T a) = Ord (T a)++So we may need to do a little work on the givens to expose the+class that has the superclasses. That's why the superclass+expansion for Givens happens in canClassNC.++This same scenario happens with quantified constraints, whose superclasses+are also eagerly expanded. Test case: typecheck/should_compile/T16502b+These are handled in canForAllNC, analogously to canClassNC.++Note [Why adding superclasses can help]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Examples of how adding superclasses can help:++ --- Example 1+ class C a b | a -> b+ Suppose we want to solve+ [G] C a b+ [W] C a beta+ Then adding [D] beta~b will let us solve it.++ -- Example 2 (similar but using a type-equality superclass)+ class (F a ~ b) => C a b+ And try to sllve:+ [G] C a b+ [W] C a beta+ Follow the superclass rules to add+ [G] F a ~ b+ [D] F a ~ beta+ Now we get [D] beta ~ b, and can solve that.++ -- Example (tcfail138)+ class L a b | a -> b+ class (G a, L a b) => C a b++ instance C a b' => G (Maybe a)+ instance C a b => C (Maybe a) a+ instance L (Maybe a) a++ When solving the superclasses of the (C (Maybe a) a) instance, we get+ [G] C a b, and hance by superclasses, [G] G a, [G] L a b+ [W] G (Maybe a)+ Use the instance decl to get+ [W] C a beta+ Generate its derived superclass+ [D] L a beta. Now using fundeps, combine with [G] L a b to get+ [D] beta ~ b+ which is what we want.++Note [Danger of adding superclasses during solving]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Here's a serious, but now out-dated example, from #4497:++ class Num (RealOf t) => Normed t+ type family RealOf x++Assume the generated wanted constraint is:+ [W] RealOf e ~ e+ [W] Normed e++If we were to be adding the superclasses during simplification we'd get:+ [W] RealOf e ~ e+ [W] Normed e+ [D] RealOf e ~ fuv+ [D] Num fuv+==>+ e := fuv, Num fuv, Normed fuv, RealOf fuv ~ fuv++While looks exactly like our original constraint. If we add the+superclass of (Normed fuv) again we'd loop. By adding superclasses+definitely only once, during canonicalisation, this situation can't+happen.++Mind you, now that Wanteds cannot rewrite Derived, I think this particular+situation can't happen.++Note [Nested quantified constraint superclasses]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider (typecheck/should_compile/T17202)++ class C1 a+ class (forall c. C1 c) => C2 a+ class (forall b. (b ~ F a) => C2 a) => C3 a++Elsewhere in the code, we get a [G] g1 :: C3 a. We expand its superclass+to get [G] g2 :: (forall b. (b ~ F a) => C2 a). This constraint has a+superclass, as well. But we now must be careful: we cannot just add+(forall c. C1 c) as a Given, because we need to remember g2's context.+That new constraint is Given only when forall b. (b ~ F a) is true.++It's tempting to make the new Given be (forall b. (b ~ F a) => forall c. C1 c),+but that's problematic, because it's nested, and ForAllPred is not capable+of representing a nested quantified constraint. (We could change ForAllPred+to allow this, but the solution in this Note is much more local and simpler.)++So, we swizzle it around to get (forall b c. (b ~ F a) => C1 c).++More generally, if we are expanding the superclasses of+ g0 :: forall tvs. theta => cls tys+and find a superclass constraint+ forall sc_tvs. sc_theta => sc_inner_pred+we must have a selector+ sel_id :: forall cls_tvs. cls cls_tvs -> forall sc_tvs. sc_theta => sc_inner_pred+and thus build+ g_sc :: forall tvs sc_tvs. theta => sc_theta => sc_inner_pred+ g_sc = /\ tvs. /\ sc_tvs. \ theta_ids. \ sc_theta_ids.+ sel_id tys (g0 tvs theta_ids) sc_tvs sc_theta_ids++Actually, we cheat a bit by eta-reducing: note that sc_theta_ids are both the+last bound variables and the last arguments. This avoids the need to produce+the sc_theta_ids at all. So our final construction is++ g_sc = /\ tvs. /\ sc_tvs. \ theta_ids.+ sel_id tys (g0 tvs theta_ids) sc_tvs++ -}++makeSuperClasses :: [Ct] -> TcS [Ct]+-- Returns strict superclasses, transitively, see Note [The superclasses story]+-- See Note [The superclass story]+-- The loop-breaking here follows Note [Expanding superclasses] in GHC.Tc.Utils.TcType+-- Specifically, for an incoming (C t) constraint, we return all of (C t)'s+-- superclasses, up to /and including/ the first repetition of C+--+-- Example: class D a => C a+-- class C [a] => D a+-- makeSuperClasses (C x) will return (D x, C [x])+--+-- NB: the incoming constraints have had their cc_pend_sc flag already+-- flipped to False, by isPendingScDict, so we are /obliged/ to at+-- least produce the immediate superclasses+makeSuperClasses cts = concatMapM go cts+ where+ go (CDictCan { cc_ev = ev, cc_class = cls, cc_tyargs = tys })+ = mkStrictSuperClasses ev [] [] cls tys+ go (CQuantCan (QCI { qci_pred = pred, qci_ev = ev }))+ = ASSERT2( isClassPred pred, ppr pred ) -- The cts should all have+ -- class pred heads+ mkStrictSuperClasses ev tvs theta cls tys+ where+ (tvs, theta, cls, tys) = tcSplitDFunTy (ctEvPred ev)+ go ct = pprPanic "makeSuperClasses" (ppr ct)++mkStrictSuperClasses+ :: CtEvidence+ -> [TyVar] -> ThetaType -- These two args are non-empty only when taking+ -- superclasses of a /quantified/ constraint+ -> Class -> [Type] -> TcS [Ct]+-- Return constraints for the strict superclasses of+-- ev :: forall as. theta => cls tys+mkStrictSuperClasses ev tvs theta cls tys+ = mk_strict_superclasses (unitNameSet (className cls))+ ev tvs theta cls tys++mk_strict_superclasses :: NameSet -> CtEvidence+ -> [TyVar] -> ThetaType+ -> Class -> [Type] -> TcS [Ct]+-- Always return the immediate superclasses of (cls tys);+-- and expand their superclasses, provided none of them are in rec_clss+-- nor are repeated+mk_strict_superclasses rec_clss (CtGiven { ctev_evar = evar, ctev_loc = loc })+ tvs theta cls tys+ = concatMapM (do_one_given (mk_given_loc loc)) $+ classSCSelIds cls+ where+ dict_ids = mkTemplateLocals theta+ size = sizeTypes tys++ do_one_given given_loc sel_id+ | isUnliftedType sc_pred+ , not (null tvs && null theta)+ = -- See Note [Equality superclasses in quantified constraints]+ return []+ | otherwise+ = do { given_ev <- newGivenEvVar given_loc $+ mk_given_desc sel_id sc_pred+ ; mk_superclasses rec_clss given_ev tvs theta sc_pred }+ where+ sc_pred = classMethodInstTy sel_id tys++ -- See Note [Nested quantified constraint superclasses]+ mk_given_desc :: Id -> PredType -> (PredType, EvTerm)+ mk_given_desc sel_id sc_pred+ = (swizzled_pred, swizzled_evterm)+ where+ (sc_tvs, sc_rho) = splitForAllTyCoVars sc_pred+ (sc_theta, sc_inner_pred) = splitFunTys sc_rho++ all_tvs = tvs `chkAppend` sc_tvs+ all_theta = theta `chkAppend` (map scaledThing sc_theta)+ swizzled_pred = mkInfSigmaTy all_tvs all_theta sc_inner_pred++ -- evar :: forall tvs. theta => cls tys+ -- sel_id :: forall cls_tvs. cls cls_tvs+ -- -> forall sc_tvs. sc_theta => sc_inner_pred+ -- swizzled_evterm :: forall tvs sc_tvs. theta => sc_theta => sc_inner_pred+ swizzled_evterm = EvExpr $+ mkLams all_tvs $+ mkLams dict_ids $+ Var sel_id+ `mkTyApps` tys+ `App` (evId evar `mkVarApps` (tvs ++ dict_ids))+ `mkVarApps` sc_tvs++ mk_given_loc loc+ | isCTupleClass cls+ = loc -- For tuple predicates, just take them apart, without+ -- adding their (large) size into the chain. When we+ -- get down to a base predicate, we'll include its size.+ -- #10335++ | GivenOrigin skol_info <- ctLocOrigin loc+ -- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance+ -- for explantation of this transformation for givens+ = case skol_info of+ InstSkol -> loc { ctl_origin = GivenOrigin (InstSC size) }+ InstSC n -> loc { ctl_origin = GivenOrigin (InstSC (n `max` size)) }+ _ -> loc++ | otherwise -- Probably doesn't happen, since this function+ = loc -- is only used for Givens, but does no harm++mk_strict_superclasses rec_clss ev tvs theta cls tys+ | all noFreeVarsOfType tys+ = return [] -- Wanteds with no variables yield no deriveds.+ -- See Note [Improvement from Ground Wanteds]++ | otherwise -- Wanted/Derived case, just add Derived superclasses+ -- that can lead to improvement.+ = ASSERT2( null tvs && null theta, ppr tvs $$ ppr theta )+ concatMapM do_one_derived (immSuperClasses cls tys)+ where+ loc = ctEvLoc ev++ do_one_derived sc_pred+ = do { sc_ev <- newDerivedNC loc sc_pred+ ; mk_superclasses rec_clss sc_ev [] [] sc_pred }++{- Note [Improvement from Ground Wanteds]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose class C b a => D a b+and consider+ [W] D Int Bool+Is there any point in emitting [D] C Bool Int? No! The only point of+emitting superclass constraints for W/D constraints is to get+improvement, extra unifications that result from functional+dependencies. See Note [Why adding superclasses can help] above.++But no variables means no improvement; case closed.+-}++mk_superclasses :: NameSet -> CtEvidence+ -> [TyVar] -> ThetaType -> PredType -> TcS [Ct]+-- Return this constraint, plus its superclasses, if any+mk_superclasses rec_clss ev tvs theta pred+ | ClassPred cls tys <- classifyPredType pred+ = mk_superclasses_of rec_clss ev tvs theta cls tys++ | otherwise -- Superclass is not a class predicate+ = return [mkNonCanonical ev]++mk_superclasses_of :: NameSet -> CtEvidence+ -> [TyVar] -> ThetaType -> Class -> [Type]+ -> TcS [Ct]+-- Always return this class constraint,+-- and expand its superclasses+mk_superclasses_of rec_clss ev tvs theta cls tys+ | loop_found = do { traceTcS "mk_superclasses_of: loop" (ppr cls <+> ppr tys)+ ; return [this_ct] } -- cc_pend_sc of this_ct = True+ | otherwise = do { traceTcS "mk_superclasses_of" (vcat [ ppr cls <+> ppr tys+ , ppr (isCTupleClass cls)+ , ppr rec_clss+ ])+ ; sc_cts <- mk_strict_superclasses rec_clss' ev tvs theta cls tys+ ; return (this_ct : sc_cts) }+ -- cc_pend_sc of this_ct = False+ where+ cls_nm = className cls+ loop_found = not (isCTupleClass cls) && cls_nm `elemNameSet` rec_clss+ -- Tuples never contribute to recursion, and can be nested+ rec_clss' = rec_clss `extendNameSet` cls_nm++ this_ct | null tvs, null theta+ = CDictCan { cc_ev = ev, cc_class = cls, cc_tyargs = tys+ , cc_pend_sc = loop_found }+ -- NB: If there is a loop, we cut off, so we have not+ -- added the superclasses, hence cc_pend_sc = True+ | otherwise+ = CQuantCan (QCI { qci_tvs = tvs, qci_pred = mkClassPred cls tys+ , qci_ev = ev+ , qci_pend_sc = loop_found })+++{- Note [Equality superclasses in quantified constraints]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider (#15359, #15593, #15625)+ f :: (forall a. theta => a ~ b) => stuff++It's a bit odd to have a local, quantified constraint for `(a~b)`,+but some people want such a thing (see the tickets). And for+Coercible it is definitely useful+ f :: forall m. (forall p q. Coercible p q => Coercible (m p) (m q)))+ => stuff++Moreover it's not hard to arrange; we just need to look up /equality/+constraints in the quantified-constraint environment, which we do in+GHC.Tc.Solver.Interact.doTopReactOther.++There is a wrinkle though, in the case where 'theta' is empty, so+we have+ f :: (forall a. a~b) => stuff++Now, potentially, the superclass machinery kicks in, in+makeSuperClasses, giving us a a second quantified constraint+ (forall a. a ~# b)+BUT this is an unboxed value! And nothing has prepared us for+dictionary "functions" that are unboxed. Actually it does just+about work, but the simplifier ends up with stuff like+ case (/\a. eq_sel d) of df -> ...(df @Int)...+and fails to simplify that any further. And it doesn't satisfy+isPredTy any more.++So for now we simply decline to take superclasses in the quantified+case. Instead we have a special case in GHC.Tc.Solver.Interact.doTopReactOther,+which looks for primitive equalities specially in the quantified+constraints.++See also Note [Evidence for quantified constraints] in GHC.Core.Predicate.+++************************************************************************+* *+* Irreducibles canonicalization+* *+************************************************************************+-}++canIrred :: CtEvidence -> TcS (StopOrContinue Ct)+-- Precondition: ty not a tuple and no other evidence form+canIrred ev+ = do { let pred = ctEvPred ev+ ; traceTcS "can_pred" (text "IrredPred = " <+> ppr pred)+ ; (xi,co) <- rewrite ev pred -- co :: xi ~ pred+ ; rewriteEvidence ev xi co `andWhenContinue` \ new_ev ->++ do { -- Re-classify, in case rewriting has improved its shape+ -- Code is like the canNC, except+ -- that the IrredPred branch stops work+ ; case classifyPredType (ctEvPred new_ev) of+ ClassPred cls tys -> canClassNC new_ev cls tys+ EqPred eq_rel ty1 ty2 -> canEqNC new_ev eq_rel ty1 ty2+ ForAllPred tvs th p -> -- this is highly suspect; Quick Look+ -- should never leave a meta-var filled+ -- in with a polytype. This is #18987.+ do traceTcS "canEvNC:forall" (ppr pred)+ canForAllNC ev tvs th p+ IrredPred {} -> continueWith $+ mkIrredCt OtherCIS new_ev } }++{- *********************************************************************+* *+* Quantified predicates+* *+********************************************************************* -}++{- Note [Quantified constraints]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The -XQuantifiedConstraints extension allows type-class contexts like this:++ data Rose f x = Rose x (f (Rose f x))++ instance (Eq a, forall b. Eq b => Eq (f b))+ => Eq (Rose f a) where+ (Rose x1 rs1) == (Rose x2 rs2) = x1==x2 && rs1 == rs2++Note the (forall b. Eq b => Eq (f b)) in the instance contexts.+This quantified constraint is needed to solve the+ [W] (Eq (f (Rose f x)))+constraint which arises form the (==) definition.++The wiki page is+ https://gitlab.haskell.org/ghc/ghc/wikis/quantified-constraints+which in turn contains a link to the GHC Proposal where the change+is specified, and a Haskell Symposium paper about it.++We implement two main extensions to the design in the paper:++ 1. We allow a variable in the instance head, e.g.+ f :: forall m a. (forall b. m b) => D (m a)+ Notice the 'm' in the head of the quantified constraint, not+ a class.++ 2. We support superclasses to quantified constraints.+ For example (contrived):+ f :: (Ord b, forall b. Ord b => Ord (m b)) => m a -> m a -> Bool+ f x y = x==y+ Here we need (Eq (m a)); but the quantified constraint deals only+ with Ord. But we can make it work by using its superclass.++Here are the moving parts+ * Language extension {-# LANGUAGE QuantifiedConstraints #-}+ and add it to ghc-boot-th:GHC.LanguageExtensions.Type.Extension++ * A new form of evidence, EvDFun, that is used to discharge+ such wanted constraints++ * checkValidType gets some changes to accept forall-constraints+ only in the right places.++ * Predicate.Pred gets a new constructor ForAllPred, and+ and classifyPredType analyses a PredType to decompose+ the new forall-constraints++ * GHC.Tc.Solver.Monad.InertCans gets an extra field, inert_insts,+ which holds all the Given forall-constraints. In effect,+ such Given constraints are like local instance decls.++ * When trying to solve a class constraint, via+ GHC.Tc.Solver.Interact.matchInstEnv, use the InstEnv from inert_insts+ so that we include the local Given forall-constraints+ in the lookup. (See GHC.Tc.Solver.Monad.getInstEnvs.)++ * GHC.Tc.Solver.Canonical.canForAll deals with solving a+ forall-constraint. See+ Note [Solving a Wanted forall-constraint]++ * We augment the kick-out code to kick out an inert+ forall constraint if it can be rewritten by a new+ type equality; see GHC.Tc.Solver.Monad.kick_out_rewritable++Note that a quantified constraint is never /inferred/+(by GHC.Tc.Solver.simplifyInfer). A function can only have a+quantified constraint in its type if it is given an explicit+type signature.++-}++canForAllNC :: CtEvidence -> [TyVar] -> TcThetaType -> TcPredType+ -> TcS (StopOrContinue Ct)+canForAllNC ev tvs theta pred+ | isGiven ev -- See Note [Eagerly expand given superclasses]+ , Just (cls, tys) <- cls_pred_tys_maybe+ = do { sc_cts <- mkStrictSuperClasses ev tvs theta cls tys+ ; emitWork sc_cts+ ; canForAll ev False }++ | otherwise+ = canForAll ev (isJust cls_pred_tys_maybe)++ where+ cls_pred_tys_maybe = getClassPredTys_maybe pred++canForAll :: CtEvidence -> Bool -> TcS (StopOrContinue Ct)+-- We have a constraint (forall as. blah => C tys)+canForAll ev pend_sc+ = do { -- First rewrite it to apply the current substitution+ let pred = ctEvPred ev+ ; (xi,co) <- rewrite ev pred -- co :: xi ~ pred+ ; rewriteEvidence ev xi co `andWhenContinue` \ new_ev ->++ do { -- Now decompose into its pieces and solve it+ -- (It takes a lot less code to rewrite before decomposing.)+ ; case classifyPredType (ctEvPred new_ev) of+ ForAllPred tvs theta pred+ -> solveForAll new_ev tvs theta pred pend_sc+ _ -> pprPanic "canForAll" (ppr new_ev)+ } }++solveForAll :: CtEvidence -> [TyVar] -> TcThetaType -> PredType -> Bool+ -> TcS (StopOrContinue Ct)+solveForAll ev tvs theta pred pend_sc+ | CtWanted { ctev_dest = dest } <- ev+ = -- See Note [Solving a Wanted forall-constraint]+ do { let skol_info = QuantCtxtSkol+ empty_subst = mkEmptyTCvSubst $ mkInScopeSet $+ tyCoVarsOfTypes (pred:theta) `delVarSetList` tvs+ ; (subst, skol_tvs) <- tcInstSkolTyVarsX empty_subst tvs+ ; given_ev_vars <- mapM newEvVar (substTheta subst theta)++ ; (lvl, (w_id, wanteds))+ <- pushLevelNoWorkList (ppr skol_info) $+ do { wanted_ev <- newWantedEvVarNC loc $+ substTy subst pred+ ; return ( ctEvEvId wanted_ev+ , unitBag (mkNonCanonical wanted_ev)) }++ ; ev_binds <- emitImplicationTcS lvl skol_info skol_tvs+ given_ev_vars wanteds++ ; setWantedEvTerm dest $+ EvFun { et_tvs = skol_tvs, et_given = given_ev_vars+ , et_binds = ev_binds, et_body = w_id }++ ; stopWith ev "Wanted forall-constraint" }++ | isGiven ev -- See Note [Solving a Given forall-constraint]+ = do { addInertForAll qci+ ; stopWith ev "Given forall-constraint" }++ | otherwise+ = do { traceTcS "discarding derived forall-constraint" (ppr ev)+ ; stopWith ev "Derived forall-constraint" }+ where+ loc = ctEvLoc ev+ qci = QCI { qci_ev = ev, qci_tvs = tvs+ , qci_pred = pred, qci_pend_sc = pend_sc }++{- Note [Solving a Wanted forall-constraint]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Solving a wanted forall (quantified) constraint+ [W] df :: forall ab. (Eq a, Ord b) => C x a b+is delightfully easy. Just build an implication constraint+ forall ab. (g1::Eq a, g2::Ord b) => [W] d :: C x a+and discharge df thus:+ df = /\ab. \g1 g2. let <binds> in d+where <binds> is filled in by solving the implication constraint.+All the machinery is to hand; there is little to do.++Note [Solving a Given forall-constraint]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+For a Given constraint+ [G] df :: forall ab. (Eq a, Ord b) => C x a b+we just add it to TcS's local InstEnv of known instances,+via addInertForall. Then, if we look up (C x Int Bool), say,+we'll find a match in the InstEnv.+++************************************************************************+* *+* Equalities+* *+************************************************************************++Note [Canonicalising equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In order to canonicalise an equality, we look at the structure of the+two types at hand, looking for similarities. A difficulty is that the+types may look dissimilar before rewriting but similar after rewriting.+However, we don't just want to jump in and rewrite right away, because+this might be wasted effort. So, after looking for similarities and failing,+we rewrite and then try again. Of course, we don't want to loop, so we+track whether or not we've already rewritten.++It is conceivable to do a better job at tracking whether or not a type+is rewritten, but this is left as future work. (Mar '15)+++Note [Decomposing FunTy]+~~~~~~~~~~~~~~~~~~~~~~~~+can_eq_nc' may attempt to decompose a FunTy that is un-zonked. This+means that we may very well have a FunTy containing a type of some+unknown kind. For instance, we may have,++ FunTy (a :: k) Int++Where k is a unification variable. So the calls to getRuntimeRep_maybe may+fail (returning Nothing). In that case we'll fall through, zonk, and try again.+Zonking should fill the variable k, meaning that decomposition will succeed the+second time around.++Also note that we require the AnonArgFlag to match. This will stop+us decomposing+ (Int -> Bool) ~ (Show a => blah)+It's as if we treat (->) and (=>) as different type constructors.+-}++canEqNC :: CtEvidence -> EqRel -> Type -> Type -> TcS (StopOrContinue Ct)+canEqNC ev eq_rel ty1 ty2+ = do { result <- zonk_eq_types ty1 ty2+ ; case result of+ Left (Pair ty1' ty2') -> can_eq_nc False ev eq_rel ty1' ty1 ty2' ty2+ Right ty -> canEqReflexive ev eq_rel ty }++can_eq_nc+ :: Bool -- True => both types are rewritten+ -> CtEvidence+ -> EqRel+ -> Type -> Type -- LHS, after and before type-synonym expansion, resp+ -> Type -> Type -- RHS, after and before type-synonym expansion, resp+ -> TcS (StopOrContinue Ct)+can_eq_nc rewritten ev eq_rel ty1 ps_ty1 ty2 ps_ty2+ = do { traceTcS "can_eq_nc" $+ vcat [ ppr rewritten, ppr ev, ppr eq_rel, ppr ty1, ppr ps_ty1, ppr ty2, ppr ps_ty2 ]+ ; rdr_env <- getGlobalRdrEnvTcS+ ; fam_insts <- getFamInstEnvs+ ; can_eq_nc' rewritten rdr_env fam_insts ev eq_rel ty1 ps_ty1 ty2 ps_ty2 }++can_eq_nc'+ :: Bool -- True => both input types are rewritten+ -> GlobalRdrEnv -- needed to see which newtypes are in scope+ -> FamInstEnvs -- needed to unwrap data instances+ -> CtEvidence+ -> EqRel+ -> Type -> Type -- LHS, after and before type-synonym expansion, resp+ -> Type -> Type -- RHS, after and before type-synonym expansion, resp+ -> TcS (StopOrContinue Ct)++-- See Note [Comparing nullary type synonyms] in GHC.Core.Type.+can_eq_nc' _flat _rdr_env _envs ev eq_rel ty1@(TyConApp tc1 []) _ps_ty1 (TyConApp tc2 []) _ps_ty2+ | tc1 == tc2+ = canEqReflexive ev eq_rel ty1++-- Expand synonyms first; see Note [Type synonyms and canonicalization]+can_eq_nc' rewritten rdr_env envs ev eq_rel ty1 ps_ty1 ty2 ps_ty2+ | Just ty1' <- tcView ty1 = can_eq_nc' rewritten rdr_env envs ev eq_rel ty1' ps_ty1 ty2 ps_ty2+ | Just ty2' <- tcView ty2 = can_eq_nc' rewritten rdr_env envs ev eq_rel ty1 ps_ty1 ty2' ps_ty2++-- need to check for reflexivity in the ReprEq case.+-- See Note [Eager reflexivity check]+-- Check only when rewritten because the zonk_eq_types check in canEqNC takes+-- care of the non-rewritten case.+can_eq_nc' True _rdr_env _envs ev ReprEq ty1 _ ty2 _+ | ty1 `tcEqType` ty2+ = canEqReflexive ev ReprEq ty1++-- When working with ReprEq, unwrap newtypes.+-- See Note [Unwrap newtypes first]+-- This must be above the TyVarTy case, in order to guarantee (TyEq:N)+can_eq_nc' _rewritten rdr_env envs ev eq_rel ty1 ps_ty1 ty2 ps_ty2+ | ReprEq <- eq_rel+ , Just stuff1 <- tcTopNormaliseNewTypeTF_maybe envs rdr_env ty1+ = can_eq_newtype_nc ev NotSwapped ty1 stuff1 ty2 ps_ty2++ | ReprEq <- eq_rel+ , Just stuff2 <- tcTopNormaliseNewTypeTF_maybe envs rdr_env ty2+ = can_eq_newtype_nc ev IsSwapped ty2 stuff2 ty1 ps_ty1++-- Then, get rid of casts+can_eq_nc' rewritten _rdr_env _envs ev eq_rel (CastTy ty1 co1) _ ty2 ps_ty2+ | isNothing (canEqLHS_maybe ty2) -- See (3) in Note [Equalities with incompatible kinds]+ = canEqCast rewritten ev eq_rel NotSwapped ty1 co1 ty2 ps_ty2+can_eq_nc' rewritten _rdr_env _envs ev eq_rel ty1 ps_ty1 (CastTy ty2 co2) _+ | isNothing (canEqLHS_maybe ty1) -- See (3) in Note [Equalities with incompatible kinds]+ = canEqCast rewritten ev eq_rel IsSwapped ty2 co2 ty1 ps_ty1++----------------------+-- Otherwise try to decompose+----------------------++-- Literals+can_eq_nc' _rewritten _rdr_env _envs ev eq_rel ty1@(LitTy l1) _ (LitTy l2) _+ | l1 == l2+ = do { setEvBindIfWanted ev (evCoercion $ mkReflCo (eqRelRole eq_rel) ty1)+ ; stopWith ev "Equal LitTy" }++-- Decompose FunTy: (s -> t) and (c => t)+-- NB: don't decompose (Int -> blah) ~ (Show a => blah)+can_eq_nc' _rewritten _rdr_env _envs ev eq_rel+ (FunTy { ft_mult = am1, ft_af = af1, ft_arg = ty1a, ft_res = ty1b }) _ps_ty1+ (FunTy { ft_mult = am2, ft_af = af2, ft_arg = ty2a, ft_res = ty2b }) _ps_ty2+ | af1 == af2 -- Don't decompose (Int -> blah) ~ (Show a => blah)+ , Just ty1a_rep <- getRuntimeRep_maybe ty1a -- getRutimeRep_maybe:+ , Just ty1b_rep <- getRuntimeRep_maybe ty1b -- see Note [Decomposing FunTy]+ , Just ty2a_rep <- getRuntimeRep_maybe ty2a+ , Just ty2b_rep <- getRuntimeRep_maybe ty2b+ = canDecomposableTyConAppOK ev eq_rel funTyCon+ [am1, ty1a_rep, ty1b_rep, ty1a, ty1b]+ [am2, ty2a_rep, ty2b_rep, ty2a, ty2b]++-- Decompose type constructor applications+-- NB: we have expanded type synonyms already+can_eq_nc' _rewritten _rdr_env _envs ev eq_rel ty1 _ ty2 _+ | Just (tc1, tys1) <- tcSplitTyConApp_maybe ty1+ , Just (tc2, tys2) <- tcSplitTyConApp_maybe ty2+ -- we want to catch e.g. Maybe Int ~ (Int -> Int) here for better+ -- error messages rather than decomposing into AppTys;+ -- hence no direct match on TyConApp+ , not (isTypeFamilyTyCon tc1)+ , not (isTypeFamilyTyCon tc2)+ = canTyConApp ev eq_rel tc1 tys1 tc2 tys2++can_eq_nc' _rewritten _rdr_env _envs ev eq_rel+ s1@(ForAllTy (Bndr _ vis1) _) _+ s2@(ForAllTy (Bndr _ vis2) _) _+ | vis1 `sameVis` vis2 -- Note [ForAllTy and typechecker equality]+ = can_eq_nc_forall ev eq_rel s1 s2++-- See Note [Canonicalising type applications] about why we require rewritten types+-- Use tcSplitAppTy, not matching on AppTy, to catch oversaturated type families+-- NB: Only decompose AppTy for nominal equality. See Note [Decomposing equality]+can_eq_nc' True _rdr_env _envs ev NomEq ty1 _ ty2 _+ | Just (t1, s1) <- tcSplitAppTy_maybe ty1+ , Just (t2, s2) <- tcSplitAppTy_maybe ty2+ = can_eq_app ev t1 s1 t2 s2++-------------------+-- Can't decompose.+-------------------++-- No similarity in type structure detected. Rewrite and try again.+can_eq_nc' False rdr_env envs ev eq_rel _ ps_ty1 _ ps_ty2+ = do { (xi1, co1) <- rewrite ev ps_ty1+ ; (xi2, co2) <- rewrite ev ps_ty2+ ; new_ev <- rewriteEqEvidence ev NotSwapped xi1 xi2 co1 co2+ ; can_eq_nc' True rdr_env envs new_ev eq_rel xi1 xi1 xi2 xi2 }++----------------------------+-- Look for a canonical LHS. See Note [Canonical LHS].+-- Only rewritten types end up below here.+----------------------------++-- NB: pattern match on True: we want only rewritten types sent to canEqLHS+-- This means we've rewritten any variables and reduced any type family redexes+-- See also Note [No top-level newtypes on RHS of representational equalities]+can_eq_nc' True _rdr_env _envs ev eq_rel ty1 ps_ty1 ty2 ps_ty2+ | Just can_eq_lhs1 <- canEqLHS_maybe ty1+ = canEqCanLHS ev eq_rel NotSwapped can_eq_lhs1 ps_ty1 ty2 ps_ty2++ | Just can_eq_lhs2 <- canEqLHS_maybe ty2+ = canEqCanLHS ev eq_rel IsSwapped can_eq_lhs2 ps_ty2 ty1 ps_ty1++ -- If the type is TyConApp tc1 args1, then args1 really can't be less+ -- than tyConArity tc1. It could be *more* than tyConArity, but then we+ -- should have handled the case as an AppTy. That case only fires if+ -- _both_ sides of the equality are AppTy-like... but if one side is+ -- AppTy-like and the other isn't (and it also isn't a variable or+ -- saturated type family application, both of which are handled by+ -- can_eq_nc'), we're in a failure mode and can just fall through.++----------------------------+-- Fall-through. Give up.+----------------------------++-- We've rewritten and the types don't match. Give up.+can_eq_nc' True _rdr_env _envs ev eq_rel _ ps_ty1 _ ps_ty2+ = do { traceTcS "can_eq_nc' catch-all case" (ppr ps_ty1 $$ ppr ps_ty2)+ ; case eq_rel of -- See Note [Unsolved equalities]+ ReprEq -> continueWith (mkIrredCt OtherCIS ev)+ NomEq -> continueWith (mkIrredCt InsolubleCIS ev) }+ -- No need to call canEqFailure/canEqHardFailure because they+ -- rewrite, and the types involved here are already rewritten++{- Note [Unsolved equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+If we have an unsolved equality like+ (a b ~R# Int)+that is not necessarily insoluble! Maybe 'a' will turn out to be a newtype.+So we want to make it a potentially-soluble Irred not an insoluble one.+Missing this point is what caused #15431++Note [ForAllTy and typechecker equality]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Should GHC type-check the following program (adapted from #15740)?++ {-# LANGUAGE PolyKinds, ... #-}+ data D a+ type family F :: forall k. k -> Type+ type instance F = D++Due to the way F is declared, any instance of F must have a right-hand side+whose kind is equal to `forall k. k -> Type`. The kind of D is+`forall {k}. k -> Type`, which is very close, but technically uses distinct+Core:++ -----------------------------------------------------------+ | Source Haskell | Core |+ -----------------------------------------------------------+ | forall k. <...> | ForAllTy (Bndr k Specified) (<...>) |+ | forall {k}. <...> | ForAllTy (Bndr k Inferred) (<...>) |+ -----------------------------------------------------------++We could deem these kinds to be unequal, but that would imply rejecting+programs like the one above. Whether a kind variable binder ends up being+specified or inferred can be somewhat subtle, however, especially for kinds+that aren't explicitly written out in the source code (like in D above).+For now, we decide to not make the specified/inferred status of an invisible+type variable binder affect GHC's notion of typechecker equality+(see Note [Typechecker equality vs definitional equality] in+GHC.Tc.Utils.TcType). That is, we have the following:++ --------------------------------------------------+ | Type 1 | Type 2 | Equal? |+ --------------------|-----------------------------+ | forall k. <...> | forall k. <...> | Yes |+ | | forall {k}. <...> | Yes |+ | | forall k -> <...> | No |+ --------------------------------------------------+ | forall {k}. <...> | forall k. <...> | Yes |+ | | forall {k}. <...> | Yes |+ | | forall k -> <...> | No |+ --------------------------------------------------+ | forall k -> <...> | forall k. <...> | No |+ | | forall {k}. <...> | No |+ | | forall k -> <...> | Yes |+ --------------------------------------------------++We implement this nuance by using the GHC.Types.Var.sameVis function in+GHC.Tc.Solver.Canonical.canEqNC and GHC.Tc.Utils.TcType.tcEqType, which+respect typechecker equality. sameVis puts both forms of invisible type+variable binders into the same equivalence class.++Note that we do /not/ use sameVis in GHC.Core.Type.eqType, which implements+/definitional/ equality, a slighty more coarse-grained notion of equality+(see Note [Non-trivial definitional equality] in GHC.Core.TyCo.Rep) that does+not consider the ArgFlag of ForAllTys at all. That is, eqType would equate all+of forall k. <...>, forall {k}. <...>, and forall k -> <...>.+-}++---------------------------------+can_eq_nc_forall :: CtEvidence -> EqRel+ -> Type -> Type -- LHS and RHS+ -> TcS (StopOrContinue Ct)+-- (forall as. phi1) ~ (forall bs. phi2)+-- Check for length match of as, bs+-- Then build an implication constraint: forall as. phi1 ~ phi2[as/bs]+-- But remember also to unify the kinds of as and bs+-- (this is the 'go' loop), and actually substitute phi2[as |> cos / bs]+-- Remember also that we might have forall z (a:z). blah+-- so we must proceed one binder at a time (#13879)++can_eq_nc_forall ev eq_rel s1 s2+ | CtWanted { ctev_loc = loc, ctev_dest = orig_dest } <- ev+ = do { let free_tvs = tyCoVarsOfTypes [s1,s2]+ (bndrs1, phi1) = tcSplitForAllTyVarBinders s1+ (bndrs2, phi2) = tcSplitForAllTyVarBinders s2+ ; if not (equalLength bndrs1 bndrs2)+ then do { traceTcS "Forall failure" $+ vcat [ ppr s1, ppr s2, ppr bndrs1, ppr bndrs2+ , ppr (map binderArgFlag bndrs1)+ , ppr (map binderArgFlag bndrs2) ]+ ; canEqHardFailure ev s1 s2 }+ else+ do { traceTcS "Creating implication for polytype equality" $ ppr ev+ ; let empty_subst1 = mkEmptyTCvSubst $ mkInScopeSet free_tvs+ ; (subst1, skol_tvs) <- tcInstSkolTyVarsX empty_subst1 $+ binderVars bndrs1++ ; let skol_info = UnifyForAllSkol phi1+ phi1' = substTy subst1 phi1++ -- Unify the kinds, extend the substitution+ go :: [TcTyVar] -> TCvSubst -> [TyVarBinder]+ -> TcS (TcCoercion, Cts)+ go (skol_tv:skol_tvs) subst (bndr2:bndrs2)+ = do { let tv2 = binderVar bndr2+ ; (kind_co, wanteds1) <- unify loc Nominal (tyVarKind skol_tv)+ (substTy subst (tyVarKind tv2))+ ; let subst' = extendTvSubstAndInScope subst tv2+ (mkCastTy (mkTyVarTy skol_tv) kind_co)+ -- skol_tv is already in the in-scope set, but the+ -- free vars of kind_co are not; hence "...AndInScope"+ ; (co, wanteds2) <- go skol_tvs subst' bndrs2+ ; return ( mkTcForAllCo skol_tv kind_co co+ , wanteds1 `unionBags` wanteds2 ) }++ -- Done: unify phi1 ~ phi2+ go [] subst bndrs2+ = ASSERT( null bndrs2 )+ unify loc (eqRelRole eq_rel) phi1' (substTyUnchecked subst phi2)++ go _ _ _ = panic "cna_eq_nc_forall" -- case (s:ss) []++ empty_subst2 = mkEmptyTCvSubst (getTCvInScope subst1)++ ; (lvl, (all_co, wanteds)) <- pushLevelNoWorkList (ppr skol_info) $+ go skol_tvs empty_subst2 bndrs2+ ; emitTvImplicationTcS lvl skol_info skol_tvs wanteds++ ; setWantedEq orig_dest all_co+ ; stopWith ev "Deferred polytype equality" } }++ | otherwise+ = do { traceTcS "Omitting decomposition of given polytype equality" $+ pprEq s1 s2 -- See Note [Do not decompose given polytype equalities]+ ; stopWith ev "Discard given polytype equality" }++ where+ unify :: CtLoc -> Role -> TcType -> TcType -> TcS (TcCoercion, Cts)+ -- This version returns the wanted constraint rather+ -- than putting it in the work list+ unify loc role ty1 ty2+ | ty1 `tcEqType` ty2+ = return (mkTcReflCo role ty1, emptyBag)+ | otherwise+ = do { (wanted, co) <- newWantedEq loc role ty1 ty2+ ; return (co, unitBag (mkNonCanonical wanted)) }++---------------------------------+-- | Compare types for equality, while zonking as necessary. Gives up+-- as soon as it finds that two types are not equal.+-- This is quite handy when some unification has made two+-- types in an inert Wanted to be equal. We can discover the equality without+-- rewriting, which is sometimes very expensive (in the case of type functions).+-- In particular, this function makes a ~20% improvement in test case+-- perf/compiler/T5030.+--+-- Returns either the (partially zonked) types in the case of+-- inequality, or the one type in the case of equality. canEqReflexive is+-- a good next step in the 'Right' case. Returning 'Left' is always safe.+--+-- NB: This does *not* look through type synonyms. In fact, it treats type+-- synonyms as rigid constructors. In the future, it might be convenient+-- to look at only those arguments of type synonyms that actually appear+-- in the synonym RHS. But we're not there yet.+zonk_eq_types :: TcType -> TcType -> TcS (Either (Pair TcType) TcType)+zonk_eq_types = go+ where+ go (TyVarTy tv1) (TyVarTy tv2) = tyvar_tyvar tv1 tv2+ go (TyVarTy tv1) ty2 = tyvar NotSwapped tv1 ty2+ go ty1 (TyVarTy tv2) = tyvar IsSwapped tv2 ty1++ -- We handle FunTys explicitly here despite the fact that they could also be+ -- treated as an application. Why? Well, for one it's cheaper to just look+ -- at two types (the argument and result types) than four (the argument,+ -- result, and their RuntimeReps). Also, we haven't completely zonked yet,+ -- so we may run into an unzonked type variable while trying to compute the+ -- RuntimeReps of the argument and result types. This can be observed in+ -- testcase tc269.+ go ty1 ty2+ | Just (Scaled w1 arg1, res1) <- split1+ , Just (Scaled w2 arg2, res2) <- split2+ , eqType w1 w2+ = do { res_a <- go arg1 arg2+ ; res_b <- go res1 res2+ ; return $ combine_rev (mkVisFunTy w1) res_b res_a+ }+ | isJust split1 || isJust split2+ = bale_out ty1 ty2+ where+ split1 = tcSplitFunTy_maybe ty1+ split2 = tcSplitFunTy_maybe ty2++ go ty1 ty2+ | Just (tc1, tys1) <- repSplitTyConApp_maybe ty1+ , Just (tc2, tys2) <- repSplitTyConApp_maybe ty2+ = if tc1 == tc2 && tys1 `equalLength` tys2+ -- Crucial to check for equal-length args, because+ -- we cannot assume that the two args to 'go' have+ -- the same kind. E.g go (Proxy * (Maybe Int))+ -- (Proxy (*->*) Maybe)+ -- We'll call (go (Maybe Int) Maybe)+ -- See #13083+ then tycon tc1 tys1 tys2+ else bale_out ty1 ty2++ go ty1 ty2+ | Just (ty1a, ty1b) <- tcRepSplitAppTy_maybe ty1+ , Just (ty2a, ty2b) <- tcRepSplitAppTy_maybe ty2+ = do { res_a <- go ty1a ty2a+ ; res_b <- go ty1b ty2b+ ; return $ combine_rev mkAppTy res_b res_a }++ go ty1@(LitTy lit1) (LitTy lit2)+ | lit1 == lit2+ = return (Right ty1)++ go ty1 ty2 = bale_out ty1 ty2+ -- We don't handle more complex forms here++ bale_out ty1 ty2 = return $ Left (Pair ty1 ty2)++ tyvar :: SwapFlag -> TcTyVar -> TcType+ -> TcS (Either (Pair TcType) TcType)+ -- Try to do as little as possible, as anything we do here is redundant+ -- with rewriting. In particular, no need to zonk kinds. That's why+ -- we don't use the already-defined zonking functions+ tyvar swapped tv ty+ = case tcTyVarDetails tv of+ MetaTv { mtv_ref = ref }+ -> do { cts <- readTcRef ref+ ; case cts of+ Flexi -> give_up+ Indirect ty' -> do { trace_indirect tv ty'+ ; unSwap swapped go ty' ty } }+ _ -> give_up+ where+ give_up = return $ Left $ unSwap swapped Pair (mkTyVarTy tv) ty++ tyvar_tyvar tv1 tv2+ | tv1 == tv2 = return (Right (mkTyVarTy tv1))+ | otherwise = do { (ty1', progress1) <- quick_zonk tv1+ ; (ty2', progress2) <- quick_zonk tv2+ ; if progress1 || progress2+ then go ty1' ty2'+ else return $ Left (Pair (TyVarTy tv1) (TyVarTy tv2)) }++ trace_indirect tv ty+ = traceTcS "Following filled tyvar (zonk_eq_types)"+ (ppr tv <+> equals <+> ppr ty)++ quick_zonk tv = case tcTyVarDetails tv of+ MetaTv { mtv_ref = ref }+ -> do { cts <- readTcRef ref+ ; case cts of+ Flexi -> return (TyVarTy tv, False)+ Indirect ty' -> do { trace_indirect tv ty'+ ; return (ty', True) } }+ _ -> return (TyVarTy tv, False)++ -- This happens for type families, too. But recall that failure+ -- here just means to try harder, so it's OK if the type function+ -- isn't injective.+ tycon :: TyCon -> [TcType] -> [TcType]+ -> TcS (Either (Pair TcType) TcType)+ tycon tc tys1 tys2+ = do { results <- zipWithM go tys1 tys2+ ; return $ case combine_results results of+ Left tys -> Left (mkTyConApp tc <$> tys)+ Right tys -> Right (mkTyConApp tc tys) }++ combine_results :: [Either (Pair TcType) TcType]+ -> Either (Pair [TcType]) [TcType]+ combine_results = bimap (fmap reverse) reverse .+ foldl' (combine_rev (:)) (Right [])++ -- combine (in reverse) a new result onto an already-combined result+ combine_rev :: (a -> b -> c)+ -> Either (Pair b) b+ -> Either (Pair a) a+ -> Either (Pair c) c+ combine_rev f (Left list) (Left elt) = Left (f <$> elt <*> list)+ combine_rev f (Left list) (Right ty) = Left (f <$> pure ty <*> list)+ combine_rev f (Right tys) (Left elt) = Left (f <$> elt <*> pure tys)+ combine_rev f (Right tys) (Right ty) = Right (f ty tys)++{- See Note [Unwrap newtypes first]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider+ newtype N m a = MkN (m a)+Then N will get a conservative, Nominal role for its second parameter 'a',+because it appears as an argument to the unknown 'm'. Now consider+ [W] N Maybe a ~R# N Maybe b++If we decompose, we'll get+ [W] a ~N# b++But if instead we unwrap we'll get+ [W] Maybe a ~R# Maybe b+which in turn gives us+ [W] a ~R# b+which is easier to satisfy.++Bottom line: unwrap newtypes before decomposing them!+c.f. #9123 comment:52,53 for a compelling example.++Note [Newtypes can blow the stack]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we have++ newtype X = MkX (Int -> X)+ newtype Y = MkY (Int -> Y)++and now wish to prove++ [W] X ~R Y++This Wanted will loop, expanding out the newtypes ever deeper looking+for a solid match or a solid discrepancy. Indeed, there is something+appropriate to this looping, because X and Y *do* have the same representation,+in the limit -- they're both (Fix ((->) Int)). However, no finitely-sized+coercion will ever witness it. This loop won't actually cause GHC to hang,+though, because we check our depth when unwrapping newtypes.++Note [Eager reflexivity check]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we have++ newtype X = MkX (Int -> X)++and++ [W] X ~R X++Naively, we would start unwrapping X and end up in a loop. Instead,+we do this eager reflexivity check. This is necessary only for representational+equality because the rewriter technology deals with the similar case+(recursive type families) for nominal equality.++Note that this check does not catch all cases, but it will catch the cases+we're most worried about, types like X above that are actually inhabited.++Here's another place where this reflexivity check is key:+Consider trying to prove (f a) ~R (f a). The AppTys in there can't+be decomposed, because representational equality isn't congruent with respect+to AppTy. So, when canonicalising the equality above, we get stuck and+would normally produce a CIrredCan. However, we really do want to+be able to solve (f a) ~R (f a). So, in the representational case only,+we do a reflexivity check.++(This would be sound in the nominal case, but unnecessary, and I [Richard+E.] am worried that it would slow down the common case.)+-}++------------------------+-- | We're able to unwrap a newtype. Update the bits accordingly.+can_eq_newtype_nc :: CtEvidence -- ^ :: ty1 ~ ty2+ -> SwapFlag+ -> TcType -- ^ ty1+ -> ((Bag GlobalRdrElt, TcCoercion), TcType) -- ^ :: ty1 ~ ty1'+ -> TcType -- ^ ty2+ -> TcType -- ^ ty2, with type synonyms+ -> TcS (StopOrContinue Ct)+can_eq_newtype_nc ev swapped ty1 ((gres, co), ty1') ty2 ps_ty2+ = do { traceTcS "can_eq_newtype_nc" $+ vcat [ ppr ev, ppr swapped, ppr co, ppr gres, ppr ty1', ppr ty2 ]++ -- check for blowing our stack:+ -- See Note [Newtypes can blow the stack]+ ; checkReductionDepth (ctEvLoc ev) ty1++ -- Next, we record uses of newtype constructors, since coercing+ -- through newtypes is tantamount to using their constructors.+ ; addUsedGREs gre_list+ -- If a newtype constructor was imported, don't warn about not+ -- importing it...+ ; traverse_ keepAlive $ map greMangledName gre_list+ -- ...and similarly, if a newtype constructor was defined in the same+ -- module, don't warn about it being unused.+ -- See Note [Tracking unused binding and imports] in GHC.Tc.Utils.++ ; new_ev <- rewriteEqEvidence ev swapped ty1' ps_ty2+ (mkTcSymCo co) (mkTcReflCo Representational ps_ty2)+ ; can_eq_nc False new_ev ReprEq ty1' ty1' ty2 ps_ty2 }+ where+ gre_list = bagToList gres++---------+-- ^ Decompose a type application.+-- All input types must be rewritten. See Note [Canonicalising type applications]+-- Nominal equality only!+can_eq_app :: CtEvidence -- :: s1 t1 ~N s2 t2+ -> Xi -> Xi -- s1 t1+ -> Xi -> Xi -- s2 t2+ -> TcS (StopOrContinue Ct)++-- AppTys only decompose for nominal equality, so this case just leads+-- to an irreducible constraint; see typecheck/should_compile/T10494+-- See Note [Decomposing AppTy at representational role]+can_eq_app ev s1 t1 s2 t2+ | CtDerived {} <- ev+ = do { unifyDeriveds loc [Nominal, Nominal] [s1, t1] [s2, t2]+ ; stopWith ev "Decomposed [D] AppTy" }++ | CtWanted { ctev_dest = dest } <- ev+ = do { co_s <- unifyWanted loc Nominal s1 s2+ ; let arg_loc+ | isNextArgVisible s1 = loc+ | otherwise = updateCtLocOrigin loc toInvisibleOrigin+ ; co_t <- unifyWanted arg_loc Nominal t1 t2+ ; let co = mkAppCo co_s co_t+ ; setWantedEq dest co+ ; stopWith ev "Decomposed [W] AppTy" }++ -- If there is a ForAll/(->) mismatch, the use of the Left coercion+ -- below is ill-typed, potentially leading to a panic in splitTyConApp+ -- Test case: typecheck/should_run/Typeable1+ -- We could also include this mismatch check above (for W and D), but it's slow+ -- and we'll get a better error message not doing it+ | s1k `mismatches` s2k+ = canEqHardFailure ev (s1 `mkAppTy` t1) (s2 `mkAppTy` t2)++ | CtGiven { ctev_evar = evar } <- ev+ = do { let co = mkTcCoVarCo evar+ co_s = mkTcLRCo CLeft co+ co_t = mkTcLRCo CRight co+ ; evar_s <- newGivenEvVar loc ( mkTcEqPredLikeEv ev s1 s2+ , evCoercion co_s )+ ; evar_t <- newGivenEvVar loc ( mkTcEqPredLikeEv ev t1 t2+ , evCoercion co_t )+ ; emitWorkNC [evar_t]+ ; canEqNC evar_s NomEq s1 s2 }++ where+ loc = ctEvLoc ev++ s1k = tcTypeKind s1+ s2k = tcTypeKind s2++ k1 `mismatches` k2+ = isForAllTy k1 && not (isForAllTy k2)+ || not (isForAllTy k1) && isForAllTy k2++-----------------------+-- | Break apart an equality over a casted type+-- looking like (ty1 |> co1) ~ ty2 (modulo a swap-flag)+canEqCast :: Bool -- are both types rewritten?+ -> CtEvidence+ -> EqRel+ -> SwapFlag+ -> TcType -> Coercion -- LHS (res. RHS), ty1 |> co1+ -> TcType -> TcType -- RHS (res. LHS), ty2 both normal and pretty+ -> TcS (StopOrContinue Ct)+canEqCast rewritten ev eq_rel swapped ty1 co1 ty2 ps_ty2+ = do { traceTcS "Decomposing cast" (vcat [ ppr ev+ , ppr ty1 <+> text "|>" <+> ppr co1+ , ppr ps_ty2 ])+ ; new_ev <- rewriteEqEvidence ev swapped ty1 ps_ty2+ (mkTcGReflRightCo role ty1 co1)+ (mkTcReflCo role ps_ty2)+ ; can_eq_nc rewritten new_ev eq_rel ty1 ty1 ty2 ps_ty2 }+ where+ role = eqRelRole eq_rel++------------------------+canTyConApp :: CtEvidence -> EqRel+ -> TyCon -> [TcType]+ -> TyCon -> [TcType]+ -> TcS (StopOrContinue Ct)+-- See Note [Decomposing TyConApps]+-- Neither tc1 nor tc2 is a saturated funTyCon+canTyConApp ev eq_rel tc1 tys1 tc2 tys2+ | tc1 == tc2+ , tys1 `equalLength` tys2+ = do { inerts <- getTcSInerts+ ; if can_decompose inerts+ then canDecomposableTyConAppOK ev eq_rel tc1 tys1 tys2+ else canEqFailure ev eq_rel ty1 ty2 }++ -- See Note [Skolem abstract data] (at tyConSkolem)+ | tyConSkolem tc1 || tyConSkolem tc2+ = do { traceTcS "canTyConApp: skolem abstract" (ppr tc1 $$ ppr tc2)+ ; continueWith (mkIrredCt OtherCIS ev) }++ -- Fail straight away for better error messages+ -- See Note [Use canEqFailure in canDecomposableTyConApp]+ | eq_rel == ReprEq && not (isGenerativeTyCon tc1 Representational &&+ isGenerativeTyCon tc2 Representational)+ = canEqFailure ev eq_rel ty1 ty2+ | otherwise+ = canEqHardFailure ev ty1 ty2+ where+ -- Reconstruct the types for error messages. This would do+ -- the wrong thing (from a pretty printing point of view)+ -- for functions, because we've lost the AnonArgFlag; but+ -- in fact we never call canTyConApp on a saturated FunTyCon+ ty1 = mkTyConApp tc1 tys1+ ty2 = mkTyConApp tc2 tys2++ loc = ctEvLoc ev+ pred = ctEvPred ev++ -- See Note [Decomposing equality]+ can_decompose inerts+ = isInjectiveTyCon tc1 (eqRelRole eq_rel)+ || (ctEvFlavour ev /= Given && isEmptyBag (matchableGivens loc pred inerts))++{-+Note [Use canEqFailure in canDecomposableTyConApp]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We must use canEqFailure, not canEqHardFailure here, because there is+the possibility of success if working with a representational equality.+Here is one case:++ type family TF a where TF Char = Bool+ data family DF a+ newtype instance DF Bool = MkDF Int++Suppose we are canonicalising (Int ~R DF (TF a)), where we don't yet+know `a`. This is *not* a hard failure, because we might soon learn+that `a` is, in fact, Char, and then the equality succeeds.++Here is another case:++ [G] Age ~R Int++where Age's constructor is not in scope. We don't want to report+an "inaccessible code" error in the context of this Given!++For example, see typecheck/should_compile/T10493, repeated here:++ import Data.Ord (Down) -- no constructor++ foo :: Coercible (Down Int) Int => Down Int -> Int+ foo = coerce++That should compile, but only because we use canEqFailure and not+canEqHardFailure.++Note [Decomposing equality]+~~~~~~~~~~~~~~~~~~~~~~~~~~~+If we have a constraint (of any flavour and role) that looks like+T tys1 ~ T tys2, what can we conclude about tys1 and tys2? The answer,+of course, is "it depends". This Note spells it all out.++In this Note, "decomposition" refers to taking the constraint+ [fl] (T tys1 ~X T tys2)+(for some flavour fl and some role X) and replacing it with+ [fls'] (tys1 ~Xs' tys2)+where that notation indicates a list of new constraints, where the+new constraints may have different flavours and different roles.++The key property to consider is injectivity. When decomposing a Given, the+decomposition is sound if and only if T is injective in all of its type+arguments. When decomposing a Wanted, the decomposition is sound (assuming the+correct roles in the produced equality constraints), but it may be a guess --+that is, an unforced decision by the constraint solver. Decomposing Wanteds+over injective TyCons does not entail guessing. But sometimes we want to+decompose a Wanted even when the TyCon involved is not injective! (See below.)++So, in broad strokes, we want this rule:++(*) Decompose a constraint (T tys1 ~X T tys2) if and only if T is injective+at role X.++Pursuing the details requires exploring three axes:+* Flavour: Given vs. Derived vs. Wanted+* Role: Nominal vs. Representational+* TyCon species: datatype vs. newtype vs. data family vs. type family vs. type variable++(A type variable isn't a TyCon, of course, but it's convenient to put the AppTy case+in the same table.)++Right away, we can say that Derived behaves just as Wanted for the purposes+of decomposition. The difference between Derived and Wanted is the handling of+evidence. Since decomposition in these cases isn't a matter of soundness but of+guessing, we want the same behaviour regardless of evidence.++Here is a table (discussion following) detailing where decomposition of+ (T s1 ... sn) ~r (T t1 .. tn)+is allowed. The first four lines (Data types ... type family) refer+to TyConApps with various TyCons T; the last line is for AppTy, covering+both where there is a type variable at the head and the case for an over-+saturated type family.++NOMINAL GIVEN WANTED WHERE++Datatype YES YES canTyConApp+Newtype YES YES canTyConApp+Data family YES YES canTyConApp+Type family NO{1} YES, in injective args{1} canEqCanLHS2+AppTy YES YES can_eq_app++REPRESENTATIONAL GIVEN WANTED++Datatype YES YES canTyConApp+Newtype NO{2} MAYBE{2} canTyConApp(can_decompose)+Data family NO{3} MAYBE{3} canTyConApp(can_decompose)+Type family NO NO canEqCanLHS2+AppTy NO{4} NO{4} can_eq_nc'++{1}: Type families can be injective in some, but not all, of their arguments,+so we want to do partial decomposition. This is quite different than the way+other decomposition is done, where the decomposed equalities replace the original+one. We thus proceed much like we do with superclasses, emitting new Deriveds+when "decomposing" a partially-injective type family Wanted. Injective type+families have no corresponding evidence of their injectivity, so we cannot+decompose an injective-type-family Given.++{2}: See Note [Decomposing newtypes at representational role]++{3}: Because of the possibility of newtype instances, we must treat+data families like newtypes. See also+Note [Decomposing newtypes at representational role]. See #10534 and+test case typecheck/should_fail/T10534.++{4}: See Note [Decomposing AppTy at representational role]++In the implementation of can_eq_nc and friends, we don't directly pattern+match using lines like in the tables above, as those tables don't cover+all cases (what about PrimTyCon? tuples?). Instead we just ask about injectivity,+boiling the tables above down to rule (*). The exceptions to rule (*) are for+injective type families, which are handled separately from other decompositions,+and the MAYBE entries above.++Note [Decomposing newtypes at representational role]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+This note discusses the 'newtype' line in the REPRESENTATIONAL table+in Note [Decomposing equality]. (At nominal role, newtypes are fully+decomposable.)++Here is a representative example of why representational equality over+newtypes is tricky:++ newtype Nt a = Mk Bool -- NB: a is not used in the RHS,+ type role Nt representational -- but the user gives it an R role anyway++If we have [W] Nt alpha ~R Nt beta, we *don't* want to decompose to+[W] alpha ~R beta, because it's possible that alpha and beta aren't+representationally equal. Here's another example.++ newtype Nt a = MkNt (Id a)+ type family Id a where Id a = a++ [W] Nt Int ~R Nt Age++Because of its use of a type family, Nt's parameter will get inferred to have+a nominal role. Thus, decomposing the wanted will yield [W] Int ~N Age, which+is unsatisfiable. Unwrapping, though, leads to a solution.++Conclusion:+ * Unwrap newtypes before attempting to decompose them.+ This is done in can_eq_nc'.++It all comes from the fact that newtypes aren't necessarily injective+w.r.t. representational equality.++Furthermore, as explained in Note [NthCo and newtypes] in GHC.Core.TyCo.Rep, we can't use+NthCo on representational coercions over newtypes. NthCo comes into play+only when decomposing givens.++Conclusion:+ * Do not decompose [G] N s ~R N t++Is it sensible to decompose *Wanted* constraints over newtypes? Yes!+It's the only way we could ever prove (IO Int ~R IO Age), recalling+that IO is a newtype.++However we must be careful. Consider++ type role Nt representational++ [G] Nt a ~R Nt b (1)+ [W] NT alpha ~R Nt b (2)+ [W] alpha ~ a (3)++If we focus on (3) first, we'll substitute in (2), and now it's+identical to the given (1), so we succeed. But if we focus on (2)+first, and decompose it, we'll get (alpha ~R b), which is not soluble.+This is exactly like the question of overlapping Givens for class+constraints: see Note [Instance and Given overlap] in GHC.Tc.Solver.Interact.++Conclusion:+ * Decompose [W] N s ~R N t iff there no given constraint that could+ later solve it.++Note [Decomposing AppTy at representational role]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We never decompose AppTy at a representational role. For Givens, doing+so is simply unsound: the LRCo coercion former requires a nominal-roled+arguments. (See (1) for an example of why.) For Wanteds, decomposing+would be sound, but it would be a guess, and a non-confluent one at that.++Here is an example:++ [G] g1 :: a ~R b+ [W] w1 :: Maybe b ~R alpha a+ [W] w2 :: alpha ~ Maybe++Suppose we see w1 before w2. If we were to decompose, we would decompose+this to become++ [W] w3 :: Maybe ~R alpha+ [W] w4 :: b ~ a++Note that w4 is *nominal*. A nominal role here is necessary because AppCo+requires a nominal role on its second argument. (See (2) for an example of+why.) If we decomposed w1 to w3,w4, we would then get stuck, because w4+is insoluble. On the other hand, if we see w2 first, setting alpha := Maybe,+all is well, as we can decompose Maybe b ~R Maybe a into b ~R a.++Another example:++ newtype Phant x = MkPhant Int++ [W] w1 :: Phant Int ~R alpha Bool+ [W] w2 :: alpha ~ Phant++If we see w1 first, decomposing would be disastrous, as we would then try+to solve Int ~ Bool. Instead, spotting w2 allows us to simplify w1 to become++ [W] w1' :: Phant Int ~R Phant Bool++which can then (assuming MkPhant is in scope) be simplified to Int ~R Int,+and all will be well. See also Note [Unwrap newtypes first].++Bottom line: never decompose AppTy with representational roles.++(1) Decomposing a Given AppTy over a representational role is simply+unsound. For example, if we have co1 :: Phant Int ~R a Bool (for+the newtype Phant, above), then we surely don't want any relationship+between Int and Bool, lest we also have co2 :: Phant ~ a around.++(2) The role on the AppCo coercion is a conservative choice, because we don't+know the role signature of the function. For example, let's assume we could+have a representational role on the second argument of AppCo. Then, consider++ data G a where -- G will have a nominal role, as G is a GADT+ MkG :: G Int+ newtype Age = MkAge Int++ co1 :: G ~R a -- by assumption+ co2 :: Age ~R Int -- by newtype axiom+ co3 = AppCo co1 co2 :: G Age ~R a Int -- by our broken AppCo++and now co3 can be used to cast MkG to have type G Age, in violation of+the way GADTs are supposed to work (which is to use nominal equality).++-}++canDecomposableTyConAppOK :: CtEvidence -> EqRel+ -> TyCon -> [TcType] -> [TcType]+ -> TcS (StopOrContinue Ct)+-- Precondition: tys1 and tys2 are the same length, hence "OK"+canDecomposableTyConAppOK ev eq_rel tc tys1 tys2+ = ASSERT( tys1 `equalLength` tys2 )+ do { traceTcS "canDecomposableTyConAppOK"+ (ppr ev $$ ppr eq_rel $$ ppr tc $$ ppr tys1 $$ ppr tys2)+ ; case ev of+ CtDerived {}+ -> unifyDeriveds loc tc_roles tys1 tys2++ CtWanted { ctev_dest = dest }+ -- new_locs and tc_roles are both infinite, so+ -- we are guaranteed that cos has the same length+ -- as tys1 and tys2+ -> do { cos <- zipWith4M unifyWanted new_locs tc_roles tys1 tys2+ ; setWantedEq dest (mkTyConAppCo role tc cos) }++ CtGiven { ctev_evar = evar }+ -> do { let ev_co = mkCoVarCo evar+ ; given_evs <- newGivenEvVars loc $+ [ ( mkPrimEqPredRole r ty1 ty2+ , evCoercion $ mkNthCo r i ev_co )+ | (r, ty1, ty2, i) <- zip4 tc_roles tys1 tys2 [0..]+ , r /= Phantom+ , not (isCoercionTy ty1) && not (isCoercionTy ty2) ]+ ; emitWorkNC given_evs }++ ; stopWith ev "Decomposed TyConApp" }++ where+ loc = ctEvLoc ev+ role = eqRelRole eq_rel++ -- infinite, as tyConRolesX returns an infinite tail of Nominal+ tc_roles = tyConRolesX role tc++ -- Add nuances to the location during decomposition:+ -- * if the argument is a kind argument, remember this, so that error+ -- messages say "kind", not "type". This is determined based on whether+ -- the corresponding tyConBinder is named (that is, dependent)+ -- * if the argument is invisible, note this as well, again by+ -- looking at the corresponding binder+ -- For oversaturated tycons, we need the (repeat loc) tail, which doesn't+ -- do either of these changes. (Forgetting to do so led to #16188)+ --+ -- NB: infinite in length+ new_locs = [ new_loc+ | bndr <- tyConBinders tc+ , let new_loc0 | isNamedTyConBinder bndr = toKindLoc loc+ | otherwise = loc+ new_loc | isInvisibleTyConBinder bndr+ = updateCtLocOrigin new_loc0 toInvisibleOrigin+ | otherwise+ = new_loc0 ]+ ++ repeat loc++-- | Call when canonicalizing an equality fails, but if the equality is+-- representational, there is some hope for the future.+-- Examples in Note [Use canEqFailure in canDecomposableTyConApp]+canEqFailure :: CtEvidence -> EqRel+ -> TcType -> TcType -> TcS (StopOrContinue Ct)+canEqFailure ev NomEq ty1 ty2+ = canEqHardFailure ev ty1 ty2+canEqFailure ev ReprEq ty1 ty2+ = do { (xi1, co1) <- rewrite ev ty1+ ; (xi2, co2) <- rewrite ev ty2+ -- We must rewrite the types before putting them in the+ -- inert set, so that we are sure to kick them out when+ -- new equalities become available+ ; traceTcS "canEqFailure with ReprEq" $+ vcat [ ppr ev, ppr ty1, ppr ty2, ppr xi1, ppr xi2 ]+ ; new_ev <- rewriteEqEvidence ev NotSwapped xi1 xi2 co1 co2+ ; continueWith (mkIrredCt OtherCIS new_ev) }++-- | Call when canonicalizing an equality fails with utterly no hope.+canEqHardFailure :: CtEvidence+ -> TcType -> TcType -> TcS (StopOrContinue Ct)+-- See Note [Make sure that insolubles are fully rewritten]+canEqHardFailure ev ty1 ty2+ = do { traceTcS "canEqHardFailure" (ppr ty1 $$ ppr ty2)+ ; (s1, co1) <- rewrite ev ty1+ ; (s2, co2) <- rewrite ev ty2+ ; new_ev <- rewriteEqEvidence ev NotSwapped s1 s2 co1 co2+ ; continueWith (mkIrredCt InsolubleCIS new_ev) }++{-+Note [Decomposing TyConApps]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~+If we see (T s1 t1 ~ T s2 t2), then we can just decompose to+ (s1 ~ s2, t1 ~ t2)+and push those back into the work list. But if+ s1 = K k1 s2 = K k2+then we will just decomopose s1~s2, and it might be better to+do so on the spot. An important special case is where s1=s2,+and we get just Refl.++So canDecomposableTyCon is a fast-path decomposition that uses+unifyWanted etc to short-cut that work.++Note [Canonicalising type applications]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Given (s1 t1) ~ ty2, how should we proceed?+The simple thing is to see if ty2 is of form (s2 t2), and+decompose.++However, over-eager decomposition gives bad error messages+for things like+ a b ~ Maybe c+ e f ~ p -> q+Suppose (in the first example) we already know a~Array. Then if we+decompose the application eagerly, yielding+ a ~ Maybe+ b ~ c+we get an error "Can't match Array ~ Maybe",+but we'd prefer to get "Can't match Array b ~ Maybe c".++So instead can_eq_wanted_app rewrites the LHS and RHS, in the hope of+replacing (a b) by (Array b), before using try_decompose_app to+decompose it.++Note [Make sure that insolubles are fully rewritten]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When an equality fails, we still want to rewrite the equality+all the way down, so that it accurately reflects+ (a) the mutable reference substitution in force at start of solving+ (b) any ty-binds in force at this point in solving+See Note [Rewrite insolubles] in GHC.Tc.Solver.Monad.+And if we don't do this there is a bad danger that+GHC.Tc.Solver.applyTyVarDefaulting will find a variable+that has in fact been substituted.++Note [Do not decompose Given polytype equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider [G] (forall a. t1 ~ forall a. t2). Can we decompose this?+No -- what would the evidence look like? So instead we simply discard+this given evidence.+++Note [Combining insoluble constraints]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+As this point we have an insoluble constraint, like Int~Bool.++ * If it is Wanted, delete it from the cache, so that subsequent+ Int~Bool constraints give rise to separate error messages++ * But if it is Derived, DO NOT delete from cache. A class constraint+ may get kicked out of the inert set, and then have its functional+ dependency Derived constraints generated a second time. In that+ case we don't want to get two (or more) error messages by+ generating two (or more) insoluble fundep constraints from the same+ class constraint.++Note [No top-level newtypes on RHS of representational equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we're in this situation:++ work item: [W] c1 : a ~R b+ inert: [G] c2 : b ~R Id a++where+ newtype Id a = Id a++We want to make sure canEqCanLHS sees [W] a ~R a, after b is rewritten+and the Id newtype is unwrapped. This is assured by requiring only rewritten+types in canEqCanLHS *and* having the newtype-unwrapping check above+the tyvar check in can_eq_nc.++Note [Occurs check error]+~~~~~~~~~~~~~~~~~~~~~~~~~+If we have an occurs check error, are we necessarily hosed? Say our+tyvar is tv1 and the type it appears in is xi2. Because xi2 is function+free, then if we're computing w.r.t. nominal equality, then, yes, we're+hosed. Nothing good can come from (a ~ [a]). If we're computing w.r.t.+representational equality, this is a little subtler. Once again, (a ~R [a])+is a bad thing, but (a ~R N a) for a newtype N might be just fine. This+means also that (a ~ b a) might be fine, because `b` might become a newtype.++So, we must check: does tv1 appear in xi2 under any type constructor+that is generative w.r.t. representational equality? That's what+isInsolubleOccursCheck does.++See also #10715, which induced this addition.++Note [Put touchable variables on the left]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Ticket #10009, a very nasty example:++ f :: (UnF (F b) ~ b) => F b -> ()++ g :: forall a. (UnF (F a) ~ a) => a -> ()+ g _ = f (undefined :: F a)++For g we get [G] g1 : UnF (F a) ~ a+ [WD] w1 : UnF (F beta) ~ beta+ [WD] w2 : F a ~ F beta++g1 is canonical (CEqCan). It is oriented as above because a is not touchable.+See canEqTyVarFunEq.++w1 is similarly canonical, though the occurs-check in canEqTyVarFunEq is key+here.++w2 is canonical. But which way should it be oriented? As written, we'll be+stuck. When w2 is added to the inert set, nothing gets kicked out: g1 is+a Given (and Wanteds don't rewrite Givens), and w2 doesn't mention the LHS+of w2. We'll thus lose.++But if w2 is swapped around, to++ [D] w3 : F beta ~ F a++then (after emitting shadow Deriveds, etc. See GHC.Tc.Solver.Monad+Note [The improvement story and derived shadows]) we'll kick w1 out of the inert+set (it mentions the LHS of w3). We then rewrite w1 to++ [D] w4 : UnF (F a) ~ beta++and then, using g1, to++ [D] w5 : a ~ beta++at which point we can unify and go on to glory. (This rewriting actually+happens all at once, in the call to rewrite during canonicalisation.)++But what about the new LHS makes it better? It mentions a variable (beta)+that can appear in a Wanted -- a touchable metavariable never appears+in a Given. On the other hand, the original LHS mentioned only variables+that appear in Givens. We thus choose to put variables that can appear+in Wanteds on the left.++Ticket #12526 is another good example of this in action.++-}++---------------------+canEqCanLHS :: CtEvidence -- ev :: lhs ~ rhs+ -> EqRel -> SwapFlag+ -> CanEqLHS -- lhs (or, if swapped, rhs)+ -> TcType -- lhs: pretty lhs, already rewritten+ -> TcType -> TcType -- rhs: already rewritten+ -> TcS (StopOrContinue Ct)+canEqCanLHS ev eq_rel swapped lhs1 ps_xi1 xi2 ps_xi2+ | k1 `tcEqType` k2+ = canEqCanLHSHomo ev eq_rel swapped lhs1 ps_xi1 xi2 ps_xi2++ | otherwise+ = canEqCanLHSHetero ev eq_rel swapped lhs1 ps_xi1 k1 xi2 ps_xi2 k2++ where+ k1 = canEqLHSKind lhs1+ k2 = tcTypeKind xi2++canEqCanLHSHetero :: CtEvidence -- :: (xi1 :: ki1) ~ (xi2 :: ki2)+ -> EqRel -> SwapFlag+ -> CanEqLHS -> TcType -- xi1, pretty xi1+ -> TcKind -- ki1+ -> TcType -> TcType -- xi2, pretty xi2 :: ki2+ -> TcKind -- ki2+ -> TcS (StopOrContinue Ct)+canEqCanLHSHetero ev eq_rel swapped lhs1 ps_xi1 ki1 xi2 ps_xi2 ki2+ -- See Note [Equalities with incompatible kinds]+ = do { kind_co <- emit_kind_co -- :: ki2 ~N ki1++ ; let -- kind_co :: (ki2 :: *) ~N (ki1 :: *) (whether swapped or not)+ -- co1 :: kind(tv1) ~N ki1+ rhs' = xi2 `mkCastTy` kind_co -- :: ki1+ ps_rhs' = ps_xi2 `mkCastTy` kind_co -- :: ki1+ rhs_co = mkTcGReflLeftCo role xi2 kind_co+ -- rhs_co :: (xi2 |> kind_co) ~ xi2++ lhs_co = mkTcReflCo role xi1++ ; traceTcS "Hetero equality gives rise to kind equality"+ (ppr kind_co <+> dcolon <+> sep [ ppr ki2, text "~#", ppr ki1 ])+ ; type_ev <- rewriteEqEvidence ev swapped xi1 rhs' lhs_co rhs_co++ -- rewriteEqEvidence carries out the swap, so we're NotSwapped any more+ ; canEqCanLHSHomo type_ev eq_rel NotSwapped lhs1 ps_xi1 rhs' ps_rhs' }+ where+ emit_kind_co :: TcS CoercionN+ emit_kind_co+ | CtGiven { ctev_evar = evar } <- ev+ = do { let kind_co = maybe_sym $ mkTcKindCo (mkTcCoVarCo evar) -- :: k2 ~ k1+ ; kind_ev <- newGivenEvVar kind_loc (kind_pty, evCoercion kind_co)+ ; emitWorkNC [kind_ev]+ ; return (ctEvCoercion kind_ev) }++ | otherwise+ = unifyWanted kind_loc Nominal ki2 ki1++ xi1 = canEqLHSType lhs1+ loc = ctev_loc ev+ role = eqRelRole eq_rel+ kind_loc = mkKindLoc xi1 xi2 loc+ kind_pty = mkHeteroPrimEqPred liftedTypeKind liftedTypeKind ki2 ki1++ maybe_sym = case swapped of+ IsSwapped -> id -- if the input is swapped, then we already+ -- will have k2 ~ k1+ NotSwapped -> mkTcSymCo++-- guaranteed that tcTypeKind lhs == tcTypeKind rhs+canEqCanLHSHomo :: CtEvidence+ -> EqRel -> SwapFlag+ -> CanEqLHS -- lhs (or, if swapped, rhs)+ -> TcType -- pretty lhs+ -> TcType -> TcType -- rhs, pretty rhs+ -> TcS (StopOrContinue Ct)+canEqCanLHSHomo ev eq_rel swapped lhs1 ps_xi1 xi2 ps_xi2+ | (xi2', mco) <- split_cast_ty xi2+ , Just lhs2 <- canEqLHS_maybe xi2'+ = canEqCanLHS2 ev eq_rel swapped lhs1 ps_xi1 lhs2 (ps_xi2 `mkCastTyMCo` mkTcSymMCo mco) mco++ | otherwise+ = canEqCanLHSFinish ev eq_rel swapped lhs1 ps_xi2++ where+ split_cast_ty (CastTy ty co) = (ty, MCo co)+ split_cast_ty other = (other, MRefl)++-- This function deals with the case that both LHS and RHS are potential+-- CanEqLHSs.+canEqCanLHS2 :: CtEvidence -- lhs ~ (rhs |> mco)+ -- or, if swapped: (rhs |> mco) ~ lhs+ -> EqRel -> SwapFlag+ -> CanEqLHS -- lhs (or, if swapped, rhs)+ -> TcType -- pretty lhs+ -> CanEqLHS -- rhs+ -> TcType -- pretty rhs+ -> MCoercion -- :: kind(rhs) ~N kind(lhs)+ -> TcS (StopOrContinue Ct)+canEqCanLHS2 ev eq_rel swapped lhs1 ps_xi1 lhs2 ps_xi2 mco+ | lhs1 `eqCanEqLHS` lhs2+ -- It must be the case that mco is reflexive+ = canEqReflexive ev eq_rel (canEqLHSType lhs1)++ | TyVarLHS tv1 <- lhs1+ , TyVarLHS tv2 <- lhs2+ , swapOverTyVars (isGiven ev) tv1 tv2+ = do { traceTcS "canEqLHS2 swapOver" (ppr tv1 $$ ppr tv2 $$ ppr swapped)+ ; new_ev <- do_swap+ ; canEqCanLHSFinish new_ev eq_rel IsSwapped (TyVarLHS tv2)+ (ps_xi1 `mkCastTyMCo` sym_mco) }++ | TyVarLHS tv1 <- lhs1+ , TyFamLHS fun_tc2 fun_args2 <- lhs2+ = canEqTyVarFunEq ev eq_rel swapped tv1 ps_xi1 fun_tc2 fun_args2 ps_xi2 mco++ | TyFamLHS fun_tc1 fun_args1 <- lhs1+ , TyVarLHS tv2 <- lhs2+ = do { new_ev <- do_swap+ ; canEqTyVarFunEq new_ev eq_rel IsSwapped tv2 ps_xi2+ fun_tc1 fun_args1 ps_xi1 sym_mco }++ | TyFamLHS fun_tc1 fun_args1 <- lhs1+ , TyFamLHS fun_tc2 fun_args2 <- lhs2+ = do { traceTcS "canEqCanLHS2 two type families" (ppr lhs1 $$ ppr lhs2)++ -- emit derived equalities for injective type families+ ; let inj_eqns :: [TypeEqn] -- TypeEqn = Pair Type+ inj_eqns+ | ReprEq <- eq_rel = [] -- injectivity applies only for nom. eqs.+ | fun_tc1 /= fun_tc2 = [] -- if the families don't match, stop.++ | Injective inj <- tyConInjectivityInfo fun_tc1+ = [ Pair arg1 arg2+ | (arg1, arg2, True) <- zip3 fun_args1 fun_args2 inj ]++ -- built-in synonym families don't have an entry point+ -- for this use case. So, we just use sfInteractInert+ -- and pass two equal RHSs. We *could* add another entry+ -- point, but then there would be a burden to make+ -- sure the new entry point and existing ones were+ -- internally consistent. This is slightly distasteful,+ -- but it works well in practice and localises the+ -- problem.+ | Just ops <- isBuiltInSynFamTyCon_maybe fun_tc1+ = let ki1 = canEqLHSKind lhs1+ ki2 | MRefl <- mco+ = ki1 -- just a small optimisation+ | otherwise+ = canEqLHSKind lhs2++ fake_rhs1 = anyTypeOfKind ki1+ fake_rhs2 = anyTypeOfKind ki2+ in+ sfInteractInert ops fun_args1 fake_rhs1 fun_args2 fake_rhs2++ | otherwise -- ordinary, non-injective type family+ = []++ ; unless (isGiven ev) $+ mapM_ (unifyDerived (ctEvLoc ev) Nominal) inj_eqns++ ; tclvl <- getTcLevel+ ; dflags <- getDynFlags+ ; let tvs1 = tyCoVarsOfTypes fun_args1+ tvs2 = tyCoVarsOfTypes fun_args2++ swap_for_rewriting = anyVarSet (isTouchableMetaTyVar tclvl) tvs2 &&+ -- swap 'em: Note [Put touchable variables on the left]+ not (anyVarSet (isTouchableMetaTyVar tclvl) tvs1)+ -- this check is just to avoid unfruitful swapping++ -- If we have F a ~ F (F a), we want to swap.+ swap_for_occurs+ | CTE_OK <- checkTyFamEq dflags fun_tc2 fun_args2+ (mkTyConApp fun_tc1 fun_args1)+ , CTE_Occurs <- checkTyFamEq dflags fun_tc1 fun_args1+ (mkTyConApp fun_tc2 fun_args2)+ = True++ | otherwise+ = False++ ; if swap_for_rewriting || swap_for_occurs+ then do { new_ev <- do_swap+ ; canEqCanLHSFinish new_ev eq_rel IsSwapped lhs2 (ps_xi1 `mkCastTyMCo` sym_mco) }+ else finish_without_swapping }++ -- that's all the special cases. Now we just figure out which non-special case+ -- to continue to.+ | otherwise+ = finish_without_swapping++ where+ sym_mco = mkTcSymMCo mco++ do_swap = rewriteCastedEquality ev eq_rel swapped (canEqLHSType lhs1) (canEqLHSType lhs2) mco+ finish_without_swapping = canEqCanLHSFinish ev eq_rel swapped lhs1 (ps_xi2 `mkCastTyMCo` mco)+++-- This function handles the case where one side is a tyvar and the other is+-- a type family application. Which to put on the left?+-- If the tyvar is a touchable meta-tyvar, put it on the left, as this may+-- be our only shot to unify.+-- Otherwise, put the function on the left, because it's generally better to+-- rewrite away function calls. This makes types smaller. And it seems necessary:+-- [W] F alpha ~ alpha+-- [W] F alpha ~ beta+-- [W] G alpha beta ~ Int ( where we have type instance G a a = a )+-- If we end up with a stuck alpha ~ F alpha, we won't be able to solve this.+-- Test case: indexed-types/should_compile/CEqCanOccursCheck+canEqTyVarFunEq :: CtEvidence -- :: lhs ~ (rhs |> mco)+ -- or (rhs |> mco) ~ lhs if swapped+ -> EqRel -> SwapFlag+ -> TyVar -> TcType -- lhs (or if swapped rhs), pretty lhs+ -> TyCon -> [Xi] -> TcType -- rhs (or if swapped lhs) fun and args, pretty rhs+ -> MCoercion -- :: kind(rhs) ~N kind(lhs)+ -> TcS (StopOrContinue Ct)+canEqTyVarFunEq ev eq_rel swapped tv1 ps_xi1 fun_tc2 fun_args2 ps_xi2 mco+ = do { can_unify <- unifyTest ev tv1 rhs+ ; dflags <- getDynFlags+ ; if | case can_unify of { NoUnify -> False; _ -> True }+ , CTE_OK <- checkTyVarEq dflags YesTypeFamilies tv1 rhs+ -> canEqCanLHSFinish ev eq_rel swapped (TyVarLHS tv1) rhs++ | otherwise+ -> do { new_ev <- rewriteCastedEquality ev eq_rel swapped+ (mkTyVarTy tv1) (mkTyConApp fun_tc2 fun_args2)+ mco+ ; canEqCanLHSFinish new_ev eq_rel IsSwapped+ (TyFamLHS fun_tc2 fun_args2)+ (ps_xi1 `mkCastTyMCo` sym_mco) } }+ where+ sym_mco = mkTcSymMCo mco+ rhs = ps_xi2 `mkCastTyMCo` mco++data UnifyTestResult+ -- See Note [Solve by unification] in GHC.Tc.Solver.Interact+ -- which points out that having UnifySameLevel is just an optimisation;+ -- we could manage with UnifyOuterLevel alone (suitably renamed)+ = UnifySameLevel+ | UnifyOuterLevel [TcTyVar] -- Promote these+ TcLevel -- ..to this level+ | NoUnify++instance Outputable UnifyTestResult where+ ppr UnifySameLevel = text "UnifySameLevel"+ ppr (UnifyOuterLevel tvs lvl) = text "UnifyOuterLevel" <> parens (ppr lvl <+> ppr tvs)+ ppr NoUnify = text "NoUnify"++unifyTest :: CtEvidence -> TcTyVar -> TcType -> TcS UnifyTestResult+-- This is the key test for untouchability:+-- See Note [Unification preconditions] in GHC.Tc.Utils.Unify+-- and Note [Solve by unification] in GHC.Tc.Solver.Interact+unifyTest ev tv1 rhs+ | not (isGiven ev) -- See Note [Do not unify Givens]+ , MetaTv { mtv_tclvl = tv_lvl, mtv_info = info } <- tcTyVarDetails tv1+ , canSolveByUnification info rhs+ = do { ambient_lvl <- getTcLevel+ ; given_eq_lvl <- getInnermostGivenEqLevel++ ; if | tv_lvl `sameDepthAs` ambient_lvl+ -> return UnifySameLevel++ | tv_lvl `deeperThanOrSame` given_eq_lvl -- No intervening given equalities+ , all (does_not_escape tv_lvl) free_skols -- No skolem escapes+ -> return (UnifyOuterLevel free_metas tv_lvl)++ | otherwise+ -> return NoUnify }+ | otherwise+ = return NoUnify+ where+ (free_metas, free_skols) = partition isPromotableMetaTyVar $+ nonDetEltsUniqSet $+ tyCoVarsOfType rhs++ does_not_escape tv_lvl fv+ | isTyVar fv = tv_lvl `deeperThanOrSame` tcTyVarLevel fv+ | otherwise = True+ -- Coercion variables are not an escape risk+ -- If an implication binds a coercion variable, it'll have equalities,+ -- so the "intervening given equalities" test above will catch it+ -- Coercion holes get filled with coercions, so again no problem.++{- Note [Do not unify Givens]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider this GADT match+ data T a where+ T1 :: T Int+ ...++ f x = case x of+ T1 -> True+ ...++So we get f :: T alpha[1] -> beta[1]+ x :: T alpha[1]+and from the T1 branch we get the implication+ forall[2] (alpha[1] ~ Int) => beta[1] ~ Bool++Now, clearly we don't want to unify alpha:=Int! Yet at the moment we+process [G] alpha[1] ~ Int, we don't have any given-equalities in the+inert set, and hence there are no given equalities to make alpha untouchable.++(NB: if it were alpha[2] ~ Int, this argument wouldn't hold. But that+almost never happens, and will never happen at all if we cure #18929.)++Simple solution: never unify in Givens!+-}++-- The RHS here is either not CanEqLHS, or it's one that we+-- want to rewrite the LHS to (as per e.g. swapOverTyVars)+canEqCanLHSFinish :: CtEvidence+ -> EqRel -> SwapFlag+ -> CanEqLHS -- lhs (or, if swapped, rhs)+ -> TcType -- rhs, pretty rhs+ -> TcS (StopOrContinue Ct)+canEqCanLHSFinish ev eq_rel swapped lhs rhs+-- RHS is fully rewritten, but with type synonyms+-- preserved as much as possible+-- guaranteed that tyVarKind lhs == typeKind rhs, for (TyEq:K)+-- (TyEq:N) is checked in can_eq_nc', and (TyEq:TV) is handled in canEqTyVarHomo++ = do { dflags <- getDynFlags+ ; new_ev <- rewriteEqEvidence ev swapped lhs_ty rhs rewrite_co1 rewrite_co2++ -- Must do the occurs check even on tyvar/tyvar+ -- equalities, in case have x ~ (y :: ..x...)+ -- #12593+ -- guarantees (TyEq:OC), (TyEq:F), and (TyEq:H)+ -- this next line checks also for coercion holes (TyEq:H); see+ -- Note [Equalities with incompatible kinds]+ ; case canEqOK dflags eq_rel lhs rhs of+ CanEqOK ->+ do { traceTcS "canEqOK" (ppr lhs $$ ppr rhs)+ ; continueWith (CEqCan { cc_ev = new_ev, cc_lhs = lhs+ , cc_rhs = rhs, cc_eq_rel = eq_rel }) }+ -- it is possible that cc_rhs mentions the LHS if the LHS is a type+ -- family. This will cause later rewriting to potentially loop, but+ -- that will be caught by the depth counter. The other option is an+ -- occurs-check for a function application, which seems awkward.++ CanEqNotOK status+ -- See Note [Type variable cycles in Givens]+ | OtherCIS <- status+ , Given <- ctEvFlavour ev+ , TyVarLHS lhs_tv <- lhs+ , not (isCycleBreakerTyVar lhs_tv) -- See Detail (7) of Note+ , NomEq <- eq_rel+ -> do { traceTcS "canEqCanLHSFinish breaking a cycle" (ppr lhs $$ ppr rhs)+ ; new_rhs <- breakTyVarCycle (ctEvLoc ev) rhs+ ; traceTcS "new RHS:" (ppr new_rhs)+ ; let new_pred = mkPrimEqPred (mkTyVarTy lhs_tv) new_rhs+ new_new_ev = new_ev { ctev_pred = new_pred }+ -- See Detail (6) of Note [Type variable cycles in Givens]++ ; if anyRewritableTyVar True NomEq (\ _ tv -> tv == lhs_tv) new_rhs+ then do { traceTcS "Note [Type variable cycles in Givens] Detail (1)"+ (ppr new_new_ev)+ ; continueWith (mkIrredCt status new_ev) }+ else continueWith (CEqCan { cc_ev = new_new_ev, cc_lhs = lhs+ , cc_rhs = new_rhs, cc_eq_rel = eq_rel }) }++ -- We must not use it for further rewriting!+ | otherwise+ -> do { traceTcS "canEqCanLHSFinish can't make a canonical" (ppr lhs $$ ppr rhs)+ ; continueWith (mkIrredCt status new_ev) } }+ where+ role = eqRelRole eq_rel++ lhs_ty = canEqLHSType lhs++ rewrite_co1 = mkTcReflCo role lhs_ty+ rewrite_co2 = mkTcReflCo role rhs++-- | Solve a reflexive equality constraint+canEqReflexive :: CtEvidence -- ty ~ ty+ -> EqRel+ -> TcType -- ty+ -> TcS (StopOrContinue Ct) -- always Stop+canEqReflexive ev eq_rel ty+ = do { setEvBindIfWanted ev (evCoercion $+ mkTcReflCo (eqRelRole eq_rel) ty)+ ; stopWith ev "Solved by reflexivity" }++rewriteCastedEquality :: CtEvidence -- :: lhs ~ (rhs |> mco), or (rhs |> mco) ~ lhs+ -> EqRel -> SwapFlag+ -> TcType -- lhs+ -> TcType -- rhs+ -> MCoercion -- mco+ -> TcS CtEvidence -- :: (lhs |> sym mco) ~ rhs+ -- result is independent of SwapFlag+rewriteCastedEquality ev eq_rel swapped lhs rhs mco+ = rewriteEqEvidence ev swapped new_lhs new_rhs lhs_co rhs_co+ where+ new_lhs = lhs `mkCastTyMCo` sym_mco+ lhs_co = mkTcGReflLeftMCo role lhs sym_mco++ new_rhs = rhs+ rhs_co = mkTcGReflRightMCo role rhs mco++ sym_mco = mkTcSymMCo mco+ role = eqRelRole eq_rel++---------------------------------------------+-- | Result of checking whether a RHS is suitable for pairing+-- with a CanEqLHS in a CEqCan.+data CanEqOK+ = CanEqOK -- RHS is good+ | CanEqNotOK CtIrredStatus -- don't proceed; explains why++instance Outputable CanEqOK where+ ppr CanEqOK = text "CanEqOK"+ ppr (CanEqNotOK status) = text "CanEqNotOK" <+> ppr status++-- | This function establishes most of the invariants needed to make+-- a CEqCan.+--+-- TyEq:OC: Checked here.+-- TyEq:F: Checked here.+-- TyEq:K: assumed; ASSERTed here (that is, kind(lhs) = kind(rhs))+-- TyEq:N: assumed; ASSERTed here (if eq_rel is R, rhs is not a newtype)+-- TyEq:TV: not checked (this is hard to check)+-- TyEq:H: Checked here.+canEqOK :: DynFlags -> EqRel -> CanEqLHS -> Xi -> CanEqOK+canEqOK dflags eq_rel lhs rhs+ = ASSERT( good_rhs )+ case checkTypeEq dflags YesTypeFamilies lhs rhs of+ CTE_OK -> CanEqOK+ CTE_Bad -> CanEqNotOK OtherCIS+ -- Violation of TyEq:F++ CTE_HoleBlocker -> CanEqNotOK (BlockedCIS holes)+ where holes = coercionHolesOfType rhs+ -- This is the case detailed in+ -- Note [Equalities with incompatible kinds]+ -- Violation of TyEq:H++ -- These are both a violation of TyEq:OC, but we+ -- want to differentiate for better production of+ -- error messages+ CTE_Occurs | TyVarLHS tv <- lhs+ , isInsolubleOccursCheck eq_rel tv rhs -> CanEqNotOK InsolubleCIS+ -- If we have a ~ [a], it is not canonical, and in particular+ -- we don't want to rewrite existing inerts with it, otherwise+ -- we'd risk divergence in the constraint solver++ -- NB: no occCheckExpand here; see Note [Rewriting synonyms]+ -- in GHC.Tc.Solver.Rewrite++ | otherwise -> CanEqNotOK OtherCIS+ -- A representational equality with an occurs-check problem isn't+ -- insoluble! For example:+ -- a ~R b a+ -- We might learn that b is the newtype Id.+ -- But, the occurs-check certainly prevents the equality from being+ -- canonical, and we might loop if we were to use it in rewriting.++ -- This case also include type family occurs-check errors, which+ -- are not generally insoluble++ where+ good_rhs = kinds_match && not bad_newtype++ lhs_kind = canEqLHSKind lhs+ rhs_kind = tcTypeKind rhs++ kinds_match = lhs_kind `tcEqType` rhs_kind++ bad_newtype | ReprEq <- eq_rel+ , Just tc <- tyConAppTyCon_maybe rhs+ = isNewTyCon tc+ | otherwise+ = False++{- Note [Equalities with incompatible kinds]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+What do we do when we have an equality++ (tv :: k1) ~ (rhs :: k2)++where k1 and k2 differ? Easy: we create a coercion that relates k1 and+k2 and use this to cast. To wit, from++ [X] (tv :: k1) ~ (rhs :: k2)++(where [X] is [G], [W], or [D]), we go to++ [noDerived X] co :: k2 ~ k1+ [X] (tv :: k1) ~ ((rhs |> co) :: k1)++where++ noDerived G = G+ noDerived _ = W++For reasons described in Wrinkle (2) below, we want the [X] constraint to be "blocked";+that is, it should be put aside, and not used to rewrite any other constraint,+until the kind-equality on which it depends (namely 'co' above) is solved.+To achieve this+* The [X] constraint is a CIrredCan+* With a cc_status of BlockedCIS bchs+* Where 'bchs' is the set of "blocking coercion holes". The blocking coercion+ holes are the free coercion holes of [X]'s type+* When all the blocking coercion holes in the CIrredCan are filled (solved),+ we convert [X] to a CNonCanonical and put it in the work list.+All this is described in more detail in Wrinkle (2).++Wrinkles:++ (1) The noDerived step is because Derived equalities have no evidence.+ And yet we absolutely need evidence to be able to proceed here.+ Given evidence will use the KindCo coercion; Wanted evidence will+ be a coercion hole. Even a Derived hetero equality begets a Wanted+ kind equality.++ (2) Though it would be sound to do so, we must not mark the rewritten Wanted+ [W] (tv :: k1) ~ ((rhs |> co) :: k1)+ as canonical in the inert set. In particular, we must not unify tv.+ If we did, the Wanted becomes a Given (effectively), and then can+ rewrite other Wanteds. But that's bad: See Note [Wanteds do not rewrite Wanteds]+ in GHC.Tc.Types.Constraint. The problem is about poor error messages. See #11198 for+ tales of destruction.++ So, we have an invariant on CEqCan (TyEq:H) that the RHS does not have+ any coercion holes. This is checked in checkTypeEq. Any equalities that+ have such an RHS are turned into CIrredCans with a BlockedCIS status. We also+ must be sure to kick out any such CIrredCan constraints that mention coercion holes+ when those holes get filled in, so that the unification step can now proceed.++ The kicking out is done in kickOutAfterFillingCoercionHole.++ However, we must be careful: we kick out only when no coercion holes are+ left. The holes in the type are stored in the BlockedCIS CtIrredStatus.+ The extra check that there are no more remaining holes avoids+ needless work when rewriting evidence (which fills coercion holes) and+ aids efficiency.++ Moreover, kicking out when there are remaining unfilled holes can+ cause a loop in the solver in this case:+ [W] w1 :: (ty1 :: F a) ~ (ty2 :: s)+ After canonicalisation, we discover that this equality is heterogeneous.+ So we emit+ [W] co_abc :: F a ~ s+ and preserve the original as+ [W] w2 :: (ty1 |> co_abc) ~ ty2 (blocked on co_abc)+ Then, co_abc comes becomes the work item. It gets swapped in+ canEqCanLHS2 and then back again in canEqTyVarFunEq. We thus get+ co_abc := sym co_abd, and then co_abd := sym co_abe, with+ [W] co_abe :: F a ~ s+ This process has filled in co_abc. Suppose w2 were kicked out.+ When it gets processed,+ would get this whole chain going again. The solution is to+ kick out a blocked constraint only when the result of filling+ in the blocking coercion involves no further blocking coercions.+ Alternatively, we could be careful not to do unnecessary swaps during+ canonicalisation, but that seems hard to do, in general.++ (3) Suppose we have [W] (a :: k1) ~ (rhs :: k2). We duly follow the+ algorithm detailed here, producing [W] co :: k2 ~ k1, and adding+ [W] (a :: k1) ~ ((rhs |> co) :: k1) to the irreducibles. Some time+ later, we solve co, and fill in co's coercion hole. This kicks out+ the irreducible as described in (2).+ But now, during canonicalization, we see the cast+ and remove it, in canEqCast. By the time we get into canEqCanLHS, the equality+ is heterogeneous again, and the process repeats.++ To avoid this, we don't strip casts off a type if the other type+ in the equality is a CanEqLHS (the scenario above can happen with a+ type family, too. testcase: typecheck/should_compile/T13822).+ And this is an improvement regardless:+ because tyvars can, generally, unify with casted types, there's no+ reason to go through the work of stripping off the cast when the+ cast appears opposite a tyvar. This is implemented in the cast case+ of can_eq_nc'.++ (4) Reporting an error for a constraint that is blocked with status BlockedCIS+ is hard: what would we say to users? And we don't+ really need to report, because if a constraint is blocked, then+ there is unsolved wanted blocking it; that unsolved wanted will+ be reported. We thus push such errors to the bottom of the queue+ in the error-reporting code; they should never be printed.++ (4a) It would seem possible to do this filtering just based on the+ presence of a blocking coercion hole. However, this is no good,+ as it suppresses e.g. no-instance-found errors. We thus record+ a CtIrredStatus in CIrredCan and filter based on this status.+ This happened in T14584. An alternative approach is to expressly+ look for *equalities* with blocking coercion holes, but actually+ recording the blockage in a status field seems nicer.++ (4b) The error message might be printed with -fdefer-type-errors,+ so it still must exist. This is the only reason why there is+ a message at all. Otherwise, we could simply do nothing.++Historical note:++We used to do this via emitting a Derived kind equality and then parking+the heterogeneous equality as irreducible. But this new approach is much+more direct. And it doesn't produce duplicate Deriveds (as the old one did).++Note [Type synonyms and canonicalization]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We treat type synonym applications as xi types, that is, they do not+count as type function applications. However, we do need to be a bit+careful with type synonyms: like type functions they may not be+generative or injective. However, unlike type functions, they are+parametric, so there is no problem in expanding them whenever we see+them, since we do not need to know anything about their arguments in+order to expand them; this is what justifies not having to treat them+as specially as type function applications. The thing that causes+some subtleties is that we prefer to leave type synonym applications+*unexpanded* whenever possible, in order to generate better error+messages.++If we encounter an equality constraint with type synonym applications+on both sides, or a type synonym application on one side and some sort+of type application on the other, we simply must expand out the type+synonyms in order to continue decomposing the equality constraint into+primitive equality constraints. For example, suppose we have++ type F a = [Int]++and we encounter the equality++ F a ~ [b]++In order to continue we must expand F a into [Int], giving us the+equality++ [Int] ~ [b]++which we can then decompose into the more primitive equality+constraint++ Int ~ b.++However, if we encounter an equality constraint with a type synonym+application on one side and a variable on the other side, we should+NOT (necessarily) expand the type synonym, since for the purpose of+good error messages we want to leave type synonyms unexpanded as much+as possible. Hence the ps_xi1, ps_xi2 argument passed to canEqCanLHS.++Note [Type variable cycles in Givens]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider this situation (from indexed-types/should_compile/GivenLoop):++ instance C (Maybe b)+ [G] a ~ Maybe (F a)+ [W] C a++In order to solve the Wanted, we must use the Given to rewrite `a` to+Maybe (F a). But note that the Given has an occurs-check failure, and+so we can't straightforwardly add the Given to the inert set.++The key idea is to replace the (F a) in the RHS of the Given with a+fresh variable, which we'll call a CycleBreakerTv, or cbv. Then, emit+a new Given to connect cbv with F a. So our situation becomes++ instance C (Maybe b)+ [G] a ~ Maybe cbv+ [G] F a ~ cbv+ [W] C a++Note the orientation of the second Given. The type family ends up+on the left; see commentary on canEqTyVarFunEq, which decides how to+orient such cases. No special treatment for CycleBreakerTvs is+necessary. This scenario is now easily soluble, by using the first+Given to rewrite the Wanted, which can now be solved.++(The first Given actually also rewrites the second one. This causes+no trouble.)++More generally, we detect this scenario by the following characteristics:+ - a Given CEqCan constraint+ - with a tyvar on its LHS+ - with a soluble occurs-check failure+ - and a nominal equality++Having identified the scenario, we wish to replace all type family+applications on the RHS with fresh metavariables (with MetaInfo+CycleBreakerTv). This is done in breakTyVarCycle. These metavariables are+untouchable, but we also emit Givens relating the fresh variables to the type+family applications they replace.++Of course, we don't want our fresh variables leaking into e.g. error messages.+So we fill in the metavariables with their original type family applications+after we're done running the solver (in nestImplicTcS and runTcSWithEvBinds).+This is done by restoreTyVarCycles, which uses the inert_cycle_breakers field in+InertSet, which contains the pairings invented in breakTyVarCycle.++That is:++We transform+ [G] g : a ~ ...(F a)...+to+ [G] (Refl a) : F a ~ cbv -- CEqCan+ [G] g : a ~ ...cbv... -- CEqCan++Note that+* `cbv` is a fresh cycle breaker variable.+* `cbv` is a is a meta-tyvar, but it is completely untouchable.+* We track the cycle-breaker variables in inert_cycle_breakers in InertSet+* We eventually fill in the cycle-breakers, with `cbv := F a`.+ No one else fills in cycle-breakers!+* In inert_cycle_breakers, we remember the (cbv, F a) pair; that is, we+ remember the /original/ type. The [G] F a ~ cbv constraint may be rewritten+ by other givens (eg if we have another [G] a ~ (b,c), but at the end we+ still fill in with cbv := F a+* This fill-in is done when solving is complete, by restoreTyVarCycles+ in nestImplicTcS and runTcSWithEvBinds.+* The evidence for the new `F a ~ cbv` constraint is Refl, because we know this fill-in is+ ultimately going to happen.++There are drawbacks of this approach:++ 1. We apply this trick only for Givens, never for Wanted or Derived.+ It wouldn't make sense for Wanted, because Wanted never rewrite.+ But it's conceivable that a Derived would benefit from this all.+ I doubt it would ever happen, though, so I'm holding off.++ 2. We don't use this trick for representational equalities, as there+ is no concrete use case where it is helpful (unlike for nominal+ equalities). Furthermore, because function applications can be+ CanEqLHSs, but newtype applications cannot, the disparities between+ the cases are enough that it would be effortful to expand the idea+ to representational equalities. A quick attempt, with++ data family N a b++ f :: (Coercible a (N a b), Coercible (N a b) b) => a -> b+ f = coerce++ failed with "Could not match 'b' with 'b'." Further work is held off+ until when we have a concrete incentive to explore this dark corner.++Details:++ (1) We don't look under foralls, at all, when substituting away type family+ applications, because doing so can never be fruitful. Recall that we+ are in a case like [G] a ~ forall b. ... a .... Until we have a type+ family that can pull the body out from a forall, this will always be+ insoluble. Note also that the forall cannot be in an argument to a+ type family, or that outer type family application would already have+ been substituted away.++ However, we still must check to make sure that breakTyVarCycle actually+ succeeds in getting rid of all occurrences of the offending variable.+ If one is hidden under a forall, this won't be true. So we perform+ an additional check after performing the substitution.++ Skipping this check causes typecheck/should_fail/GivenForallLoop to loop.++ (2) Our goal here is to avoid loops in rewriting. We can thus skip looking+ in coercions, as we don't rewrite in coercions.+ (There is no worry about unifying a meta-variable here: this Note is+ only about Givens.)++ (3) As we're substituting, we can build ill-kinded+ types. For example, if we have Proxy (F a) b, where (b :: F a), then+ replacing this with Proxy cbv b is ill-kinded. However, we will later+ set cbv := F a, and so the zonked type will be well-kinded again.+ The temporary ill-kinded type hurts no one, and avoiding this would+ be quite painfully difficult.++ Specifically, this detail does not contravene the Purely Kinded Type Invariant+ (Note [The Purely Kinded Type Invariant (PKTI)] in GHC.Tc.Gen.HsType).+ The PKTI says that we can call typeKind on any type, without failure.+ It would be violated if we, say, replaced a kind (a -> b) with a kind c,+ because an arrow kind might be consulted in piResultTys. Here, we are+ replacing one opaque type like (F a b c) with another, cbv (opaque in+ that we never assume anything about its structure, like that it has a+ result type or a RuntimeRep argument).++ (4) The evidence for the produced Givens is all just reflexive, because+ we will eventually set the cycle-breaker variable to be the type family,+ and then, after the zonk, all will be well.++ (5) The approach here is inefficient. For instance, we could choose to+ affect only type family applications that mention the offending variable:+ in a ~ (F b, G a), we need to replace only G a, not F b. Furthermore,+ we could try to detect cases like a ~ (F a, F a) and use the same+ tyvar to replace F a. (Cf.+ Note [Flattening type-family applications when matching instances]+ in GHC.Core.Unify, which+ goes to this extra effort.) There may be other opportunities for+ improvement. However, this is really a very small corner case, always+ tickled by a user-written Given. The investment to craft a clever,+ performant solution seems unworthwhile.++ (6) We often get the predicate associated with a constraint from its+ evidence. We thus must not only make sure the generated CEqCan's+ fields have the updated RHS type, but we must also update the+ evidence itself. As in Detail (4), we don't need to change the+ evidence term (as in e.g. rewriteEqEvidence) because the cycle+ breaker variables are all zonked away by the time we examine the+ evidence. That is, we must set the ctev_pred of the ctEvidence.+ This is implemented in canEqCanLHSFinish, with a reference to+ this detail.++ (7) We don't wish to apply this magic to CycleBreakerTvs themselves.+ Consider this, from typecheck/should_compile/ContextStack2:++ type instance TF (a, b) = (TF a, TF b)+ t :: (a ~ TF (a, Int)) => ...++ [G] a ~ TF (a, Int)++ The RHS reduces, so we get++ [G] a ~ (TF a, TF Int)++ We then break cycles, to get++ [G] g1 :: a ~ (cbv1, cbv2)+ [G] g2 :: TF a ~ cbv1+ [G] g3 :: TF Int ~ cbv2++ g1 gets added to the inert set, as written. But then g2 becomes+ the work item. g1 rewrites g2 to become++ [G] TF (cbv1, cbv2) ~ cbv1++ which then uses the type instance to become++ [G] (TF cbv1, TF cbv2) ~ cbv1++ which looks remarkably like the Given we started with. If left+ unchecked, this will end up breaking cycles again, looping ad+ infinitum (and resulting in a context-stack reduction error,+ not an outright loop). The solution is easy: don't break cycles+ if the var is already a CycleBreakerTv. Instead, we mark this+ final Given as a CIrredCan with an OtherCIS status (it's not+ insoluble).++ NB: When filling in CycleBreakerTvs, we fill them in with what+ they originally stood for (e.g. cbv1 := TF a, cbv2 := TF Int),+ not what may be in a rewritten constraint.++ Not breaking cycles further (which would mean changing TF cbv1 to cbv3+ and TF cbv2 to cbv4) makes sense, because we only want to break cycles+ for user-written loopy Givens, and a CycleBreakerTv certainly isn't+ user-written.++NB: This same situation (an equality like b ~ Maybe (F b)) can arise with+Wanteds, but we have no concrete case incentivising special treatment. It+would just be a CIrredCan.++-}++{-+************************************************************************+* *+ Evidence transformation+* *+************************************************************************+-}++data StopOrContinue a+ = ContinueWith a -- The constraint was not solved, although it may have+ -- been rewritten++ | Stop CtEvidence -- The (rewritten) constraint was solved+ SDoc -- Tells how it was solved+ -- Any new sub-goals have been put on the work list+ deriving (Functor)++instance Outputable a => Outputable (StopOrContinue a) where+ ppr (Stop ev s) = text "Stop" <> parens s <+> ppr ev+ ppr (ContinueWith w) = text "ContinueWith" <+> ppr w++continueWith :: a -> TcS (StopOrContinue a)+continueWith = return . ContinueWith++stopWith :: CtEvidence -> String -> TcS (StopOrContinue a)+stopWith ev s = return (Stop ev (text s))++andWhenContinue :: TcS (StopOrContinue a)+ -> (a -> TcS (StopOrContinue b))+ -> TcS (StopOrContinue b)+andWhenContinue tcs1 tcs2+ = do { r <- tcs1+ ; case r of+ Stop ev s -> return (Stop ev s)+ ContinueWith ct -> tcs2 ct }+infixr 0 `andWhenContinue` -- allow chaining with ($)++rewriteEvidence :: CtEvidence -- old evidence+ -> TcPredType -- new predicate+ -> TcCoercion -- Of type :: new predicate ~ <type of old evidence>+ -> TcS (StopOrContinue CtEvidence)+-- Returns Just new_ev iff either (i) 'co' is reflexivity+-- or (ii) 'co' is not reflexivity, and 'new_pred' not cached+-- In either case, there is nothing new to do with new_ev+{-+ rewriteEvidence old_ev new_pred co+Main purpose: create new evidence for new_pred;+ unless new_pred is cached already+* Returns a new_ev : new_pred, with same wanted/given/derived flag as old_ev+* If old_ev was wanted, create a binding for old_ev, in terms of new_ev+* If old_ev was given, AND not cached, create a binding for new_ev, in terms of old_ev+* Returns Nothing if new_ev is already cached++ Old evidence New predicate is Return new evidence+ flavour of same flavor+ -------------------------------------------------------------------+ Wanted Already solved or in inert Nothing+ or Derived Not Just new_evidence++ Given Already in inert Nothing+ Not Just new_evidence++Note [Rewriting with Refl]+~~~~~~~~~~~~~~~~~~~~~~~~~~+If the coercion is just reflexivity then you may re-use the same+variable. But be careful! Although the coercion is Refl, new_pred+may reflect the result of unification alpha := ty, so new_pred might+not _look_ the same as old_pred, and it's vital to proceed from now on+using new_pred.++The rewriter preserves type synonyms, so they should appear in new_pred+as well as in old_pred; that is important for good error messages.+ -}+++rewriteEvidence old_ev@(CtDerived {}) new_pred _co+ = -- If derived, don't even look at the coercion.+ -- This is very important, DO NOT re-order the equations for+ -- rewriteEvidence to put the isTcReflCo test first!+ -- Why? Because for *Derived* constraints, c, the coercion, which+ -- was produced by rewriting, may contain suspended calls to+ -- (ctEvExpr c), which fails for Derived constraints.+ -- (Getting this wrong caused #7384.)+ continueWith (old_ev { ctev_pred = new_pred })++rewriteEvidence old_ev new_pred co+ | isTcReflCo co -- See Note [Rewriting with Refl]+ = continueWith (old_ev { ctev_pred = new_pred })++rewriteEvidence ev@(CtGiven { ctev_evar = old_evar, ctev_loc = loc }) new_pred co+ = do { new_ev <- newGivenEvVar loc (new_pred, new_tm)+ ; continueWith new_ev }+ where+ -- mkEvCast optimises ReflCo+ new_tm = mkEvCast (evId old_evar) (tcDowngradeRole Representational+ (ctEvRole ev)+ (mkTcSymCo co))++rewriteEvidence ev@(CtWanted { ctev_dest = dest+ , ctev_nosh = si+ , ctev_loc = loc }) new_pred co+ = do { mb_new_ev <- newWanted_SI si loc new_pred+ -- The "_SI" variant ensures that we make a new Wanted+ -- with the same shadow-info as the existing one+ -- with the same shadow-info as the existing one (#16735)+ ; MASSERT( tcCoercionRole co == ctEvRole ev )+ ; setWantedEvTerm dest+ (mkEvCast (getEvExpr mb_new_ev)+ (tcDowngradeRole Representational (ctEvRole ev) co))+ ; case mb_new_ev of+ Fresh new_ev -> continueWith new_ev+ Cached _ -> stopWith ev "Cached wanted" }+++rewriteEqEvidence :: CtEvidence -- Old evidence :: olhs ~ orhs (not swapped)+ -- or orhs ~ olhs (swapped)+ -> SwapFlag+ -> TcType -> TcType -- New predicate nlhs ~ nrhs+ -> TcCoercion -- lhs_co, of type :: nlhs ~ olhs+ -> TcCoercion -- rhs_co, of type :: nrhs ~ orhs+ -> TcS CtEvidence -- Of type nlhs ~ nrhs+-- For (rewriteEqEvidence (Given g olhs orhs) False nlhs nrhs lhs_co rhs_co)+-- we generate+-- If not swapped+-- g1 : nlhs ~ nrhs = lhs_co ; g ; sym rhs_co+-- If 'swapped'+-- g1 : nlhs ~ nrhs = lhs_co ; Sym g ; sym rhs_co+--+-- For (Wanted w) we do the dual thing.+-- New w1 : nlhs ~ nrhs+-- If not swapped+-- w : olhs ~ orhs = sym lhs_co ; w1 ; rhs_co+-- If swapped+-- w : orhs ~ olhs = sym rhs_co ; sym w1 ; lhs_co+--+-- It's all a form of rewwriteEvidence, specialised for equalities+rewriteEqEvidence old_ev swapped nlhs nrhs lhs_co rhs_co+ | CtDerived {} <- old_ev -- Don't force the evidence for a Derived+ = return (old_ev { ctev_pred = new_pred })++ | NotSwapped <- swapped+ , isTcReflCo lhs_co -- See Note [Rewriting with Refl]+ , isTcReflCo rhs_co+ = return (old_ev { ctev_pred = new_pred })++ | CtGiven { ctev_evar = old_evar } <- old_ev+ = do { let new_tm = evCoercion (lhs_co+ `mkTcTransCo` maybeTcSymCo swapped (mkTcCoVarCo old_evar)+ `mkTcTransCo` mkTcSymCo rhs_co)+ ; newGivenEvVar loc' (new_pred, new_tm) }++ | CtWanted { ctev_dest = dest, ctev_nosh = si } <- old_ev+ = do { (new_ev, hole_co) <- newWantedEq_SI si loc'+ (ctEvRole old_ev) nlhs nrhs+ -- The "_SI" variant ensures that we make a new Wanted+ -- with the same shadow-info as the existing one (#16735)+ ; let co = maybeTcSymCo swapped $+ mkSymCo lhs_co+ `mkTransCo` hole_co+ `mkTransCo` rhs_co+ ; setWantedEq dest co+ ; traceTcS "rewriteEqEvidence" (vcat [ppr old_ev, ppr nlhs, ppr nrhs, ppr co])+ ; return new_ev }++#if __GLASGOW_HASKELL__ <= 810+ | otherwise+ = panic "rewriteEvidence"+#endif+ where+ new_pred = mkTcEqPredLikeEv old_ev nlhs nrhs++ -- equality is like a type class. Bumping the depth is necessary because+ -- of recursive newtypes, where "reducing" a newtype can actually make+ -- it bigger. See Note [Newtypes can blow the stack].+ loc = ctEvLoc old_ev+ loc' = bumpCtLocDepth loc++{-+************************************************************************+* *+ Unification+* *+************************************************************************++Note [unifyWanted and unifyDerived]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When decomposing equalities we often create new wanted constraints for+(s ~ t). But what if s=t? Then it'd be faster to return Refl right away.+Similar remarks apply for Derived.++Rather than making an equality test (which traverses the structure of the+type, perhaps fruitlessly), unifyWanted traverses the common structure, and+bales out when it finds a difference by creating a new Wanted constraint.+But where it succeeds in finding common structure, it just builds a coercion+to reflect it.+-}++unifyWanted :: CtLoc -> Role+ -> TcType -> TcType -> TcS Coercion+-- Return coercion witnessing the equality of the two types,+-- emitting new work equalities where necessary to achieve that+-- Very good short-cut when the two types are equal, or nearly so+-- See Note [unifyWanted and unifyDerived]+-- The returned coercion's role matches the input parameter+unifyWanted loc Phantom ty1 ty2+ = do { kind_co <- unifyWanted loc Nominal (tcTypeKind ty1) (tcTypeKind ty2)+ ; return (mkPhantomCo kind_co ty1 ty2) }++unifyWanted loc role orig_ty1 orig_ty2+ = go orig_ty1 orig_ty2+ where+ go ty1 ty2 | Just ty1' <- tcView ty1 = go ty1' ty2+ go ty1 ty2 | Just ty2' <- tcView ty2 = go ty1 ty2'++ go (FunTy _ w1 s1 t1) (FunTy _ w2 s2 t2)+ = do { co_s <- unifyWanted loc role s1 s2+ ; co_t <- unifyWanted loc role t1 t2+ ; co_w <- unifyWanted loc Nominal w1 w2+ ; return (mkFunCo role co_w co_s co_t) }+ go (TyConApp tc1 tys1) (TyConApp tc2 tys2)+ | tc1 == tc2, tys1 `equalLength` tys2+ , isInjectiveTyCon tc1 role -- don't look under newtypes at Rep equality+ = do { cos <- zipWith3M (unifyWanted loc)+ (tyConRolesX role tc1) tys1 tys2+ ; return (mkTyConAppCo role tc1 cos) }++ go ty1@(TyVarTy tv) ty2+ = do { mb_ty <- isFilledMetaTyVar_maybe tv+ ; case mb_ty of+ Just ty1' -> go ty1' ty2+ Nothing -> bale_out ty1 ty2}+ go ty1 ty2@(TyVarTy tv)+ = do { mb_ty <- isFilledMetaTyVar_maybe tv+ ; case mb_ty of+ Just ty2' -> go ty1 ty2'+ Nothing -> bale_out ty1 ty2 }++ go ty1@(CoercionTy {}) (CoercionTy {})+ = return (mkReflCo role ty1) -- we just don't care about coercions!++ go ty1 ty2 = bale_out ty1 ty2++ bale_out ty1 ty2+ | ty1 `tcEqType` ty2 = return (mkTcReflCo role ty1)+ -- Check for equality; e.g. a ~ a, or (m a) ~ (m a)+ | otherwise = emitNewWantedEq loc role orig_ty1 orig_ty2++unifyDeriveds :: CtLoc -> [Role] -> [TcType] -> [TcType] -> TcS ()+-- See Note [unifyWanted and unifyDerived]+unifyDeriveds loc roles tys1 tys2 = zipWith3M_ (unify_derived loc) roles tys1 tys2++unifyDerived :: CtLoc -> Role -> Pair TcType -> TcS ()+-- See Note [unifyWanted and unifyDerived]+unifyDerived loc role (Pair ty1 ty2) = unify_derived loc role ty1 ty2++unify_derived :: CtLoc -> Role -> TcType -> TcType -> TcS ()+-- Create new Derived and put it in the work list+-- Should do nothing if the two types are equal+-- See Note [unifyWanted and unifyDerived]+unify_derived _ Phantom _ _ = return ()+unify_derived loc role orig_ty1 orig_ty2+ = go orig_ty1 orig_ty2+ where+ go ty1 ty2 | Just ty1' <- tcView ty1 = go ty1' ty2+ go ty1 ty2 | Just ty2' <- tcView ty2 = go ty1 ty2'++ go (FunTy _ w1 s1 t1) (FunTy _ w2 s2 t2)+ = do { unify_derived loc role s1 s2+ ; unify_derived loc role t1 t2+ ; unify_derived loc Nominal w1 w2 }+ go (TyConApp tc1 tys1) (TyConApp tc2 tys2)+ | tc1 == tc2, tys1 `equalLength` tys2+ , isInjectiveTyCon tc1 role+ = unifyDeriveds loc (tyConRolesX role tc1) tys1 tys2+ go ty1@(TyVarTy tv) ty2+ = do { mb_ty <- isFilledMetaTyVar_maybe tv+ ; case mb_ty of+ Just ty1' -> go ty1' ty2+ Nothing -> bale_out ty1 ty2 }+ go ty1 ty2@(TyVarTy tv)+ = do { mb_ty <- isFilledMetaTyVar_maybe tv+ ; case mb_ty of+ Just ty2' -> go ty1 ty2'+ Nothing -> bale_out ty1 ty2 }+ go ty1 ty2 = bale_out ty1 ty2++ bale_out ty1 ty2+ | ty1 `tcEqType` ty2 = return ()+ -- Check for equality; e.g. a ~ a, or (m a) ~ (m a)+ | otherwise = emitNewDerivedEq loc role orig_ty1 orig_ty2
− compiler/GHC/Tc/Solver/Flatten.hs
@@ -1,1951 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveFunctor #-}--{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}--module GHC.Tc.Solver.Flatten(- FlattenMode(..),- flatten, flattenKind, flattenArgsNom,- rewriteTyVar, flattenType,-- unflattenWanteds- ) where--#include "GhclibHsVersions.h"--import GHC.Prelude--import GHC.Tc.Types-import GHC.Core.TyCo.Ppr ( pprTyVar )-import GHC.Tc.Types.Constraint-import GHC.Core.Predicate-import GHC.Tc.Utils.TcType-import GHC.Core.Type-import GHC.Tc.Types.Evidence-import GHC.Core.TyCon-import GHC.Core.TyCo.Rep -- performs delicate algorithm on types-import GHC.Core.Coercion-import GHC.Types.Var-import GHC.Types.Var.Set-import GHC.Types.Var.Env-import GHC.Utils.Outputable-import GHC.Utils.Panic-import GHC.Tc.Solver.Monad as TcS-import GHC.Types.Basic( SwapFlag(..) )--import GHC.Utils.Misc-import GHC.Data.Bag-import Control.Monad-import GHC.Utils.Monad ( zipWith3M )-import Data.Foldable ( foldrM )--import Control.Arrow ( first )--{--Note [The flattening story]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-* A CFunEqCan is either of form- [G] <F xis> : F xis ~ fsk -- fsk is a FlatSkolTv- [W] x : F xis ~ fmv -- fmv is a FlatMetaTv- where- x is the witness variable- xis are function-free- fsk/fmv is a flatten skolem;- it is always untouchable (level 0)--* CFunEqCans can have any flavour: [G], [W], [WD] or [D]--* KEY INSIGHTS:-- - A given flatten-skolem, fsk, is known a-priori to be equal to- F xis (the LHS), with <F xis> evidence. The fsk is still a- unification variable, but it is "owned" by its CFunEqCan, and- is filled in (unflattened) only by unflattenGivens.-- - A unification flatten-skolem, fmv, stands for the as-yet-unknown- type to which (F xis) will eventually reduce. It is filled in--- - All fsk/fmv variables are "untouchable". To make it simple to test,- we simply give them TcLevel=0. This means that in a CTyVarEq, say,- fmv ~ Int- we NEVER unify fmv.-- - A unification flatten-skolem, fmv, ONLY gets unified when either- a) The CFunEqCan takes a step, using an axiom- b) By unflattenWanteds- They are never unified in any other form of equality.- For example [W] ffmv ~ Int is stuck; it does not unify with fmv.--* We *never* substitute in the RHS (i.e. the fsk/fmv) of a CFunEqCan.- That would destroy the invariant about the shape of a CFunEqCan,- and it would risk wanted/wanted interactions. The only way we- learn information about fsk is when the CFunEqCan takes a step.-- However we *do* substitute in the LHS of a CFunEqCan (else it- would never get to fire!)--* Unflattening:- - We unflatten Givens when leaving their scope (see unflattenGivens)- - We unflatten Wanteds at the end of each attempt to simplify the- wanteds; see unflattenWanteds, called from solveSimpleWanteds.--* Ownership of fsk/fmv. Each canonical [G], [W], or [WD]- CFunEqCan x : F xis ~ fsk/fmv- "owns" a distinct evidence variable x, and flatten-skolem fsk/fmv.- Why? We make a fresh fsk/fmv when the constraint is born;- and we never rewrite the RHS of a CFunEqCan.-- In contrast a [D] CFunEqCan /shares/ its fmv with its partner [W],- but does not "own" it. If we reduce a [D] F Int ~ fmv, where- say type instance F Int = ty, then we don't discharge fmv := ty.- Rather we simply generate [D] fmv ~ ty (in GHC.Tc.Solver.Interact.reduce_top_fun_eq,- and dischargeFmv)--* Inert set invariant: if F xis1 ~ fsk1, F xis2 ~ fsk2- then xis1 /= xis2- i.e. at most one CFunEqCan with a particular LHS--* Flattening a type (F xis):- - If we are flattening in a Wanted/Derived constraint- then create new [W] x : F xis ~ fmv- else create new [G] x : F xis ~ fsk- with fresh evidence variable x and flatten-skolem fsk/fmv-- - Add it to the work list-- - Replace (F xis) with fsk/fmv in the type you are flattening-- - You can also add the CFunEqCan to the "flat cache", which- simply keeps track of all the function applications you- have flattened.-- - If (F xis) is in the cache already, just- use its fsk/fmv and evidence x, and emit nothing.-- - No need to substitute in the flat-cache. It's not the end- of the world if we start with, say (F alpha ~ fmv1) and- (F Int ~ fmv2) and then find alpha := Int. Athat will- simply give rise to fmv1 := fmv2 via [Interacting rule] below--* Canonicalising a CFunEqCan [G/W] x : F xis ~ fsk/fmv- - Flatten xis (to substitute any tyvars; there are already no functions)- cos :: xis ~ flat_xis- - New wanted x2 :: F flat_xis ~ fsk/fmv- - Add new wanted to flat cache- - Discharge x = F cos ; x2--* [Interacting rule]- (inert) [W] x1 : F tys ~ fmv1- (work item) [W] x2 : F tys ~ fmv2- Just solve one from the other:- x2 := x1- fmv2 := fmv1- This just unites the two fsks into one.- Always solve given from wanted if poss.--* For top-level reductions, see Note [Top-level reductions for type functions]- in GHC.Tc.Solver.Interact---Why given-fsks, alone, doesn't work-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Could we get away with only flatten meta-tyvars, with no flatten-skolems? No.-- [W] w : alpha ~ [F alpha Int]-----> flatten- w = ...w'...- [W] w' : alpha ~ [fsk]- [G] <F alpha Int> : F alpha Int ~ fsk----> unify (no occurs check)- alpha := [fsk]--But since fsk = F alpha Int, this is really an occurs check error. If-that is all we know about alpha, we will succeed in constraint-solving, producing a program with an infinite type.--Even if we did finally get (g : fsk ~ Bool) by solving (F alpha Int ~ fsk)-using axiom, zonking would not see it, so (x::alpha) sitting in the-tree will get zonked to an infinite type. (Zonking always only does-refl stuff.)--Why flatten-meta-vars, alone doesn't work-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Look at Simple13, with unification-fmvs only-- [G] g : a ~ [F a]-----> Flatten given- g' = g;[x]- [G] g' : a ~ [fmv]- [W] x : F a ~ fmv----> subst a in x- g' = g;[x]- x = F g' ; x2- [W] x2 : F [fmv] ~ fmv--And now we have an evidence cycle between g' and x!--If we used a given instead (ie current story)-- [G] g : a ~ [F a]-----> Flatten given- g' = g;[x]- [G] g' : a ~ [fsk]- [G] <F a> : F a ~ fsk-----> Substitute for a- [G] g' : a ~ [fsk]- [G] F (sym g'); <F a> : F [fsk] ~ fsk---Why is it right to treat fmv's differently to ordinary unification vars?-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~- f :: forall a. a -> a -> Bool- g :: F Int -> F Int -> Bool--Consider- f (x:Int) (y:Bool)-This gives alpha~Int, alpha~Bool. There is an inconsistency,-but really only one error. SherLoc may tell you which location-is most likely, based on other occurrences of alpha.--Consider- g (x:Int) (y:Bool)-Here we get (F Int ~ Int, F Int ~ Bool), which flattens to- (fmv ~ Int, fmv ~ Bool)-But there are really TWO separate errors.-- ** We must not complain about Int~Bool. **--Moreover these two errors could arise in entirely unrelated parts of-the code. (In the alpha case, there must be *some* connection (eg-v:alpha in common envt).)--Note [Unflattening can force the solver to iterate]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Look at #10340:- type family Any :: * -- No instances- get :: MonadState s m => m s- instance MonadState s (State s) where ...-- foo :: State Any Any- foo = get--For 'foo' we instantiate 'get' at types mm ss- [WD] MonadState ss mm, [WD] mm ss ~ State Any Any-Flatten, and decompose- [WD] MonadState ss mm, [WD] Any ~ fmv- [WD] mm ~ State fmv, [WD] fmv ~ ss-Unify mm := State fmv:- [WD] MonadState ss (State fmv)- [WD] Any ~ fmv, [WD] fmv ~ ss-Now we are stuck; the instance does not match!! So unflatten:- fmv := Any- ss := Any (*)- [WD] MonadState Any (State Any)--The unification (*) represents progress, so we must do a second-round of solving; this time it succeeds. This is done by the 'go'-loop in solveSimpleWanteds.--This story does not feel right but it's the best I can do; and the-iteration only happens in pretty obscure circumstances.---************************************************************************-* *-* Examples- Here is a long series of examples I had to work through-* *-************************************************************************--Simple20-~~~~~~~~-axiom F [a] = [F a]-- [G] F [a] ~ a--->- [G] fsk ~ a- [G] [F a] ~ fsk (nc)--->- [G] F a ~ fsk2- [G] fsk ~ [fsk2]- [G] fsk ~ a--->- [G] F a ~ fsk2- [G] a ~ [fsk2]- [G] fsk ~ a-------------------------------------------indexed-types/should_compile/T44984-- [W] H (F Bool) ~ H alpha- [W] alpha ~ F Bool--->- F Bool ~ fmv0- H fmv0 ~ fmv1- H alpha ~ fmv2-- fmv1 ~ fmv2- fmv0 ~ alpha--flatten-~~~~~~~- fmv0 := F Bool- fmv1 := H (F Bool)- fmv2 := H alpha- alpha := F Bool-plus- fmv1 ~ fmv2--But these two are equal under the above assumptions.-Solve by Refl.------ under plan B, namely solve fmv1:=fmv2 eagerly ---- [W] H (F Bool) ~ H alpha- [W] alpha ~ F Bool--->- F Bool ~ fmv0- H fmv0 ~ fmv1- H alpha ~ fmv2-- fmv1 ~ fmv2- fmv0 ~ alpha--->- F Bool ~ fmv0- H fmv0 ~ fmv1- H alpha ~ fmv2 fmv2 := fmv1-- fmv0 ~ alpha--flatten- fmv0 := F Bool- fmv1 := H fmv0 = H (F Bool)- retain H alpha ~ fmv2- because fmv2 has been filled- alpha := F Bool--------------------------------indexed-types/should_failt/T4179--after solving- [W] fmv_1 ~ fmv_2- [W] A3 (FCon x) ~ fmv_1 (CFunEqCan)- [W] A3 (x (aoa -> fmv_2)) ~ fmv_2 (CFunEqCan)-------------------------------------------indexed-types/should_fail/T7729a--a) [W] BasePrimMonad (Rand m) ~ m1-b) [W] tt m1 ~ BasePrimMonad (Rand m)-----> process (b) first- BasePrimMonad (Ramd m) ~ fmv_atH- fmv_atH ~ tt m1-----> now process (a)- m1 ~ s_atH ~ tt m1 -- An obscure occurs check--------------------------------------------typecheck/TcTypeNatSimple--Original constraint- [W] x + y ~ x + alpha (non-canonical)-==>- [W] x + y ~ fmv1 (CFunEqCan)- [W] x + alpha ~ fmv2 (CFuneqCan)- [W] fmv1 ~ fmv2 (CTyEqCan)--(sigh)-------------------------------------------indexed-types/should_fail/GADTwrong1-- [G] Const a ~ ()-==> flatten- [G] fsk ~ ()- work item: Const a ~ fsk-==> fire top rule- [G] fsk ~ ()- work item fsk ~ ()--Surely the work item should rewrite to () ~ ()? Well, maybe not;-it'a very special case. More generally, our givens look like-F a ~ Int, where (F a) is not reducible.--------------------------------------------indexed_types/should_fail/T8227:--Why using a different can-rewrite rule in CFunEqCan heads-does not work.--Assuming NOT rewriting wanteds with wanteds-- Inert: [W] fsk_aBh ~ fmv_aBk -> fmv_aBk- [W] fmv_aBk ~ fsk_aBh-- [G] Scalar fsk_aBg ~ fsk_aBh- [G] V a ~ f_aBg-- Worklist includes [W] Scalar fmv_aBi ~ fmv_aBk- fmv_aBi, fmv_aBk are flatten unification variables-- Work item: [W] V fsk_aBh ~ fmv_aBi--Note that the inert wanteds are cyclic, because we do not rewrite-wanteds with wanteds.---Then we go into a loop when normalise the work-item, because we-use rewriteOrSame on the argument of V.--Conclusion: Don't make canRewrite context specific; instead use-[W] a ~ ty to rewrite a wanted iff 'a' is a unification variable.---------------------------------------------Here is a somewhat similar case:-- type family G a :: *-- blah :: (G a ~ Bool, Eq (G a)) => a -> a- blah = error "urk"-- foo x = blah x--For foo we get- [W] Eq (G a), G a ~ Bool-Flattening- [W] G a ~ fmv, Eq fmv, fmv ~ Bool-We can't simplify away the Eq Bool unless we substitute for fmv.-Maybe that doesn't matter: we would still be left with unsolved-G a ~ Bool.-----------------------------#9318 has a very simple program leading to-- [W] F Int ~ Int- [W] F Int ~ Bool--We don't want to get "Error Int~Bool". But if fmv's can rewrite-wanteds, we will-- [W] fmv ~ Int- [W] fmv ~ Bool---->- [W] Int ~ Bool---************************************************************************-* *-* FlattenEnv & FlatM-* The flattening environment & monad-* *-************************************************************************---}--type FlatWorkListRef = TcRef [Ct] -- See Note [The flattening work list]--data FlattenEnv- = FE { fe_mode :: !FlattenMode- , fe_loc :: CtLoc -- See Note [Flattener CtLoc]- -- unbanged because it's bogus in rewriteTyVar- , fe_flavour :: !CtFlavour- , fe_eq_rel :: !EqRel -- See Note [Flattener EqRels]- , fe_work :: !FlatWorkListRef } -- See Note [The flattening work list]--data FlattenMode -- Postcondition for all three: inert wrt the type substitution- = FM_FlattenAll -- Postcondition: function-free- | FM_SubstOnly -- See Note [Flattening under a forall]---- | FM_Avoid TcTyVar Bool -- See Note [Lazy flattening]--- -- Postcondition:--- -- * tyvar is only mentioned in result under a rigid path--- -- e.g. [a] is ok, but F a won't happen--- -- * If flat_top is True, top level is not a function application--- -- (but under type constructors is ok e.g. [F a])--instance Outputable FlattenMode where- ppr FM_FlattenAll = text "FM_FlattenAll"- ppr FM_SubstOnly = text "FM_SubstOnly"--eqFlattenMode :: FlattenMode -> FlattenMode -> Bool-eqFlattenMode FM_FlattenAll FM_FlattenAll = True-eqFlattenMode FM_SubstOnly FM_SubstOnly = True--- FM_Avoid tv1 b1 `eq` FM_Avoid tv2 b2 = tv1 == tv2 && b1 == b2-eqFlattenMode _ _ = False---- | The 'FlatM' monad is a wrapper around 'TcS' with the following--- extra capabilities: (1) it offers access to a 'FlattenEnv';--- and (2) it maintains the flattening worklist.--- See Note [The flattening work list].-newtype FlatM a- = FlatM { runFlatM :: FlattenEnv -> TcS a }- deriving (Functor)--instance Monad FlatM where- m >>= k = FlatM $ \env ->- do { a <- runFlatM m env- ; runFlatM (k a) env }--instance Applicative FlatM where- pure x = FlatM $ const (pure x)- (<*>) = ap--liftTcS :: TcS a -> FlatM a-liftTcS thing_inside- = FlatM $ const thing_inside--emitFlatWork :: Ct -> FlatM ()--- See Note [The flattening work list]-emitFlatWork ct = FlatM $ \env -> updTcRef (fe_work env) (ct :)---- convenient wrapper when you have a CtEvidence describing--- the flattening operation-runFlattenCtEv :: FlattenMode -> CtEvidence -> FlatM a -> TcS a-runFlattenCtEv mode ev- = runFlatten mode (ctEvLoc ev) (ctEvFlavour ev) (ctEvEqRel ev)---- Run thing_inside (which does flattening), and put all--- the work it generates onto the main work list--- See Note [The flattening work list]-runFlatten :: FlattenMode -> CtLoc -> CtFlavour -> EqRel -> FlatM a -> TcS a-runFlatten mode loc flav eq_rel thing_inside- = do { flat_ref <- newTcRef []- ; let fmode = FE { fe_mode = mode- , fe_loc = bumpCtLocDepth loc- -- See Note [Flatten when discharging CFunEqCan]- , fe_flavour = flav- , fe_eq_rel = eq_rel- , fe_work = flat_ref }- ; res <- runFlatM thing_inside fmode- ; new_flats <- readTcRef flat_ref- ; updWorkListTcS (add_flats new_flats)- ; return res }- where- add_flats new_flats wl- = wl { wl_funeqs = add_funeqs new_flats (wl_funeqs wl) }-- add_funeqs [] wl = wl- add_funeqs (f:fs) wl = add_funeqs fs (f:wl)- -- add_funeqs fs ws = reverse fs ++ ws- -- e.g. add_funeqs [f1,f2,f3] [w1,w2,w3,w4]- -- = [f3,f2,f1,w1,w2,w3,w4]--traceFlat :: String -> SDoc -> FlatM ()-traceFlat herald doc = liftTcS $ traceTcS herald doc-{-# INLINE traceFlat #-} -- see Note [INLINE conditional tracing utilities]--getFlatEnvField :: (FlattenEnv -> a) -> FlatM a-getFlatEnvField accessor- = FlatM $ \env -> return (accessor env)--getEqRel :: FlatM EqRel-getEqRel = getFlatEnvField fe_eq_rel--getRole :: FlatM Role-getRole = eqRelRole <$> getEqRel--getFlavour :: FlatM CtFlavour-getFlavour = getFlatEnvField fe_flavour--getFlavourRole :: FlatM CtFlavourRole-getFlavourRole- = do { flavour <- getFlavour- ; eq_rel <- getEqRel- ; return (flavour, eq_rel) }--getMode :: FlatM FlattenMode-getMode = getFlatEnvField fe_mode--getLoc :: FlatM CtLoc-getLoc = getFlatEnvField fe_loc--checkStackDepth :: Type -> FlatM ()-checkStackDepth ty- = do { loc <- getLoc- ; liftTcS $ checkReductionDepth loc ty }---- | Change the 'EqRel' in a 'FlatM'.-setEqRel :: EqRel -> FlatM a -> FlatM a-setEqRel new_eq_rel thing_inside- = FlatM $ \env ->- if new_eq_rel == fe_eq_rel env- then runFlatM thing_inside env- else runFlatM thing_inside (env { fe_eq_rel = new_eq_rel })---- | Change the 'FlattenMode' in a 'FlattenEnv'.-setMode :: FlattenMode -> FlatM a -> FlatM a-setMode new_mode thing_inside- = FlatM $ \env ->- if new_mode `eqFlattenMode` fe_mode env- then runFlatM thing_inside env- else runFlatM thing_inside (env { fe_mode = new_mode })---- | Make sure that flattening actually produces a coercion (in other--- words, make sure our flavour is not Derived)--- Note [No derived kind equalities]-noBogusCoercions :: FlatM a -> FlatM a-noBogusCoercions thing_inside- = FlatM $ \env ->- -- No new thunk is made if the flavour hasn't changed (note the bang).- let !env' = case fe_flavour env of- Derived -> env { fe_flavour = Wanted WDeriv }- _ -> env- in- runFlatM thing_inside env'--bumpDepth :: FlatM a -> FlatM a-bumpDepth (FlatM thing_inside)- = FlatM $ \env -> do- -- bumpDepth can be called a lot during flattening so we force the- -- new env to avoid accumulating thunks.- { let !env' = env { fe_loc = bumpCtLocDepth (fe_loc env) }- ; thing_inside env' }--{--Note [The flattening work list]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The "flattening work list", held in the fe_work field of FlattenEnv,-is a list of CFunEqCans generated during flattening. The key idea-is this. Consider flattening (Eq (F (G Int) (H Bool)):- * The flattener recursively calls itself on sub-terms before building- the main term, so it will encounter the terms in order- G Int- H Bool- F (G Int) (H Bool)- flattening to sub-goals- w1: G Int ~ fuv0- w2: H Bool ~ fuv1- w3: F fuv0 fuv1 ~ fuv2-- * Processing w3 first is BAD, because we can't reduce i t,so it'll- get put into the inert set, and later kicked out when w1, w2 are- solved. In #9872 this led to inert sets containing hundreds- of suspended calls.-- * So we want to process w1, w2 first.-- * So you might think that we should just use a FIFO deque for the work-list,- so that putting adding goals in order w1,w2,w3 would mean we processed- w1 first.-- * BUT suppose we have 'type instance G Int = H Char'. Then processing- w1 leads to a new goal- w4: H Char ~ fuv0- We do NOT want to put that on the far end of a deque! Instead we want- to put it at the *front* of the work-list so that we continue to work- on it.--So the work-list structure is this:-- * The wl_funeqs (in TcS) is a LIFO stack; we push new goals (such as w4) on- top (extendWorkListFunEq), and take new work from the top- (selectWorkItem).-- * When flattening, emitFlatWork pushes new flattening goals (like- w1,w2,w3) onto the flattening work list, fe_work, another- push-down stack.-- * When we finish flattening, we *reverse* the fe_work stack- onto the wl_funeqs stack (which brings w1 to the top).--The function runFlatten initialises the fe_work stack, and reverses-it onto wl_fun_eqs at the end.--Note [Flattener EqRels]-~~~~~~~~~~~~~~~~~~~~~~~-When flattening, we need to know which equality relation -- nominal-or representation -- we should be respecting. The only difference is-that we rewrite variables by representational equalities when fe_eq_rel-is ReprEq, and that we unwrap newtypes when flattening w.r.t.-representational equality.--Note [Flattener CtLoc]-~~~~~~~~~~~~~~~~~~~~~~-The flattener does eager type-family reduction.-Type families might loop, and we-don't want GHC to do so. A natural solution is to have a bounded depth-to these processes. A central difficulty is that such a solution isn't-quite compositional. For example, say it takes F Int 10 steps to get to Bool.-How many steps does it take to get from F Int -> F Int to Bool -> Bool?-10? 20? What about getting from Const Char (F Int) to Char? 11? 1? Hard to-know and hard to track. So, we punt, essentially. We store a CtLoc in-the FlattenEnv and just update the environment when recurring. In the-TyConApp case, where there may be multiple type families to flatten,-we just copy the current CtLoc into each branch. If any branch hits the-stack limit, then the whole thing fails.--A consequence of this is that setting the stack limits appropriately-will be essentially impossible. So, the official recommendation if a-stack limit is hit is to disable the check entirely. Otherwise, there-will be baffling, unpredictable errors.--Note [Lazy flattening]-~~~~~~~~~~~~~~~~~~~~~~-The idea of FM_Avoid mode is to flatten less aggressively. If we have- a ~ [F Int]-there seems to be no great merit in lifting out (F Int). But if it was- a ~ [G a Int]-then we *do* want to lift it out, in case (G a Int) reduces to Bool, say,-which gets rid of the occurs-check problem. (For the flat_top Bool, see-comments above and at call sites.)--HOWEVER, the lazy flattening actually seems to make type inference go-*slower*, not faster. perf/compiler/T3064 is a case in point; it gets-*dramatically* worse with FM_Avoid. I think it may be because-floating the types out means we normalise them, and that often makes-them smaller and perhaps allows more re-use of previously solved-goals. But to be honest I'm not absolutely certain, so I am leaving-FM_Avoid in the code base. What I'm removing is the unique place-where it is *used*, namely in GHC.Tc.Solver.Canonical.canEqTyVar.--See also Note [Conservative unification check] in GHC.Tc.Utils.Unify, which gives-other examples where lazy flattening caused problems.--Bottom line: FM_Avoid is unused for now (Nov 14).-Note: T5321Fun got faster when I disabled FM_Avoid- T5837 did too, but it's pathological anyway--Note [Phantoms in the flattener]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we have--data Proxy p = Proxy--and we're flattening (Proxy ty) w.r.t. ReprEq. Then, we know that `ty`-is really irrelevant -- it will be ignored when solving for representational-equality later on. So, we omit flattening `ty` entirely. This may-violate the expectation of "xi"s for a bit, but the canonicaliser will-soon throw out the phantoms when decomposing a TyConApp. (Or, the-canonicaliser will emit an insoluble, in which case the unflattened version-yields a better error message anyway.)--Note [No derived kind equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-A kind-level coercion can appear in types, via mkCastTy. So, whenever-we are generating a coercion in a dependent context (in other words,-in a kind) we need to make sure that our flavour is never Derived-(as Derived constraints have no evidence). The noBogusCoercions function-changes the flavour from Derived just for this purpose.---}--{- *********************************************************************-* *-* Externally callable flattening functions *-* *-* They are all wrapped in runFlatten, so their *-* flattening work gets put into the work list *-* *-*********************************************************************--Note [rewriteTyVar]-~~~~~~~~~~~~~~~~~~~~~~-Suppose we have an injective function F and- inert_funeqs: F t1 ~ fsk1- F t2 ~ fsk2- inert_eqs: fsk1 ~ [a]- a ~ Int- fsk2 ~ [Int]--We never rewrite the RHS (cc_fsk) of a CFunEqCan. But we /do/ want to get the-[D] t1 ~ t2 from the injectiveness of F. So we flatten cc_fsk of CFunEqCans-when trying to find derived equalities arising from injectivity.--}---- | See Note [Flattening].--- If (xi, co) <- flatten mode ev ty, then co :: xi ~r ty--- where r is the role in @ev@. If @mode@ is 'FM_FlattenAll',--- then 'xi' is almost function-free (Note [Almost function-free]--- in "GHC.Tc.Types").-flatten :: FlattenMode -> CtEvidence -> TcType- -> TcS (Xi, TcCoercion)-flatten mode ev ty- = do { traceTcS "flatten {" (ppr mode <+> ppr ty)- ; (ty', co) <- runFlattenCtEv mode ev (flatten_one ty)- ; traceTcS "flatten }" (ppr ty')- ; return (ty', co) }---- Apply the inert set as an *inert generalised substitution* to--- a variable, zonking along the way.--- See Note [inert_eqs: the inert equalities] in GHC.Tc.Solver.Monad.--- Equivalently, this flattens the variable with respect to NomEq--- in a Derived constraint. (Why Derived? Because Derived allows the--- most about of rewriting.) Returns no coercion, because we're--- using Derived constraints.--- See Note [rewriteTyVar]-rewriteTyVar :: TcTyVar -> TcS TcType-rewriteTyVar tv- = do { traceTcS "rewriteTyVar {" (ppr tv)- ; (ty, _) <- runFlatten FM_SubstOnly fake_loc Derived NomEq $- flattenTyVar tv- ; traceTcS "rewriteTyVar }" (ppr ty)- ; return ty }- where- fake_loc = pprPanic "rewriteTyVar used a CtLoc" (ppr tv)---- specialized to flattening kinds: never Derived, always Nominal--- See Note [No derived kind equalities]--- See Note [Flattening]-flattenKind :: CtLoc -> CtFlavour -> TcType -> TcS (Xi, TcCoercionN)-flattenKind loc flav ty- = do { traceTcS "flattenKind {" (ppr flav <+> ppr ty)- ; let flav' = case flav of- Derived -> Wanted WDeriv -- the WDeriv/WOnly choice matters not- _ -> flav- ; (ty', co) <- runFlatten FM_FlattenAll loc flav' NomEq (flatten_one ty)- ; traceTcS "flattenKind }" (ppr ty' $$ ppr co) -- co is never a panic- ; return (ty', co) }---- See Note [Flattening]-flattenArgsNom :: CtEvidence -> TyCon -> [TcType] -> TcS ([Xi], [TcCoercion], TcCoercionN)--- Externally-callable, hence runFlatten--- Flatten a vector of types all at once; in fact they are--- always the arguments of type family or class, so--- ctEvFlavour ev = Nominal--- and we want to flatten all at nominal role--- The kind passed in is the kind of the type family or class, call it T--- The last coercion returned has type (tcTypeKind(T xis) ~N tcTypeKind(T tys))------ For Derived constraints the returned coercion may be undefined--- because flattening may use a Derived equality ([D] a ~ ty)-flattenArgsNom ev tc tys- = do { traceTcS "flatten_args {" (vcat (map ppr tys))- ; (tys', cos, kind_co)- <- runFlattenCtEv FM_FlattenAll ev (flatten_args_tc tc (repeat Nominal) tys)- ; traceTcS "flatten }" (vcat (map ppr tys'))- ; return (tys', cos, kind_co) }---- | Flatten a type w.r.t. nominal equality. This is useful to rewrite--- a type w.r.t. any givens. It does not do type-family reduction. This--- will never emit new constraints. Call this when the inert set contains--- only givens.-flattenType :: CtLoc -> TcType -> TcS TcType-flattenType loc ty- -- More info about FM_SubstOnly in Note [Holes] in GHC.Tc.Types.Constraint- = do { (xi, _) <- runFlatten FM_SubstOnly loc Given NomEq $- flatten_one ty- -- use Given flavor so that it is rewritten- -- only w.r.t. Givens, never Wanteds/Deriveds- -- (Shouldn't matter, if only Givens are present- -- anyway)- ; return xi }--{- *********************************************************************-* *-* The main flattening functions-* *-********************************************************************* -}--{- Note [Flattening]-~~~~~~~~~~~~~~~~~~~~- flatten ty ==> (xi, co)- where- xi has no type functions, unless they appear under ForAlls- has no skolems that are mapped in the inert set- has no filled-in metavariables- co :: xi ~ ty--Key invariants:- (F0) co :: xi ~ zonk(ty)- (F1) tcTypeKind(xi) succeeds and returns a fully zonked kind- (F2) tcTypeKind(xi) `eqType` zonk(tcTypeKind(ty))--Note that it is flatten's job to flatten *every type function it sees*.-flatten is only called on *arguments* to type functions, by canEqGiven.--Flattening also:- * zonks, removing any metavariables, and- * applies the substitution embodied in the inert set--The result of flattening is *almost function-free*. See-Note [Almost function-free] in GHC.Tc.Utils.--Because flattening zonks and the returned coercion ("co" above) is also-zonked, it's possible that (co :: xi ~ ty) isn't quite true. So, instead,-we can rely on this fact:-- (F0) co :: xi ~ zonk(ty)--Note that the left-hand type of co is *always* precisely xi. The right-hand-type may or may not be ty, however: if ty has unzonked filled-in metavariables,-then the right-hand type of co will be the zonked version of ty.-It is for this reason that we-occasionally have to explicitly zonk, when (co :: xi ~ ty) is important-even before we zonk the whole program. For example, see the FTRNotFollowed-case in flattenTyVar.--Why have these invariants on flattening? Because we sometimes use tcTypeKind-during canonicalisation, and we want this kind to be zonked (e.g., see-GHC.Tc.Solver.Canonical.canEqTyVar).--Flattening is always homogeneous. That is, the kind of the result of flattening is-always the same as the kind of the input, modulo zonking. More formally:-- (F2) tcTypeKind(xi) `eqType` zonk(tcTypeKind(ty))--This invariant means that the kind of a flattened type might not itself be flat.--Recall that in comments we use alpha[flat = ty] to represent a-flattening skolem variable alpha which has been generated to stand in-for ty.------- Example of flattening a constraint: ------- flatten (List (F (G Int))) ==> (xi, cc)- where- xi = List alpha- cc = { G Int ~ beta[flat = G Int],- F beta ~ alpha[flat = F beta] }-Here- * alpha and beta are 'flattening skolem variables'.- * All the constraints in cc are 'given', and all their coercion terms- are the identity.--NB: Flattening Skolems only occur in canonical constraints, which-are never zonked, so we don't need to worry about zonking doing-accidental unflattening.--Note that we prefer to leave type synonyms unexpanded when possible,-so when the flattener encounters one, it first asks whether its-transitive expansion contains any type function applications. If so,-it expands the synonym and proceeds; if not, it simply returns the-unexpanded synonym.--Note [flatten_args performance]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-In programs with lots of type-level evaluation, flatten_args becomes-part of a tight loop. For example, see test perf/compiler/T9872a, which-calls flatten_args a whopping 7,106,808 times. It is thus important-that flatten_args be efficient.--Performance testing showed that the current implementation is indeed-efficient. It's critically important that zipWithAndUnzipM be-specialized to TcS, and it's also quite helpful to actually `inline`-it. On test T9872a, here are the allocation stats (Dec 16, 2014):-- * Unspecialized, uninlined: 8,472,613,440 bytes allocated in the heap- * Specialized, uninlined: 6,639,253,488 bytes allocated in the heap- * Specialized, inlined: 6,281,539,792 bytes allocated in the heap--To improve performance even further, flatten_args_nom is split off-from flatten_args, as nominal equality is the common case. This would-be natural to write using mapAndUnzipM, but even inlined, that function-is not as performant as a hand-written loop.-- * mapAndUnzipM, inlined: 7,463,047,432 bytes allocated in the heap- * hand-written recursion: 5,848,602,848 bytes allocated in the heap--If you make any change here, pay close attention to the T9872{a,b,c} tests-and T5321Fun.--If we need to make this yet more performant, a possible way forward is to-duplicate the flattener code for the nominal case, and make that case-faster. This doesn't seem quite worth it, yet.--Note [flatten_exact_fam_app_fully performance]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The refactor of GRefl seems to cause performance trouble for T9872x:-the allocation of flatten_exact_fam_app_fully_performance-increased. See note [Generalized reflexive coercion] in-GHC.Core.TyCo.Rep for more information about GRefl and #15192 for the-current state.--The explicit pattern match in homogenise_result helps with T9872a, b, c.--Still, it increases the expected allocation of T9872d by ~2%.--TODO: a step-by-step replay of the refactor to analyze the performance.---}--{-# INLINE flatten_args_tc #-}-flatten_args_tc- :: TyCon -- T- -> [Role] -- Role r- -> [Type] -- Arg types [t1,..,tn]- -> FlatM ( [Xi] -- List of flattened args [x1,..,xn]- -- 1-1 corresp with [t1,..,tn]- , [Coercion] -- List of arg coercions [co1,..,con]- -- 1-1 corresp with [t1,..,tn]- -- coi :: xi ~r ti- , CoercionN) -- Result coercion, rco- -- rco : (T t1..tn) ~N (T (x1 |> co1) .. (xn |> con))-flatten_args_tc tc = flatten_args all_bndrs any_named_bndrs inner_ki emptyVarSet- -- NB: TyCon kinds are always closed- where- (bndrs, named)- = ty_con_binders_ty_binders' (tyConBinders tc)- -- it's possible that the result kind has arrows (for, e.g., a type family)- -- so we must split it- (inner_bndrs, inner_ki, inner_named) = split_pi_tys' (tyConResKind tc)- !all_bndrs = bndrs `chkAppend` inner_bndrs- !any_named_bndrs = named || inner_named- -- NB: Those bangs there drop allocations in T9872{a,c,d} by 8%.--{-# INLINE flatten_args #-}-flatten_args :: [TyCoBinder] -> Bool -- Binders, and True iff any of them are- -- named.- -> Kind -> TcTyCoVarSet -- function kind; kind's free vars- -> [Role] -> [Type] -- these are in 1-to-1 correspondence- -> FlatM ([Xi], [Coercion], CoercionN)--- Coercions :: Xi ~ Type, at roles given--- Third coercion :: tcTypeKind(fun xis) ~N tcTypeKind(fun tys)--- That is, the third coercion relates the kind of some function (whose kind is--- passed as the first parameter) instantiated at xis to the kind of that--- function instantiated at the tys. This is useful in keeping flattening--- homoegeneous. The list of roles must be at least as long as the list of--- types.-flatten_args orig_binders- any_named_bndrs- orig_inner_ki- orig_fvs- orig_roles- orig_tys- = if any_named_bndrs- then flatten_args_slow orig_binders- orig_inner_ki- orig_fvs- orig_roles- orig_tys- else flatten_args_fast orig_binders orig_inner_ki orig_roles orig_tys--{-# INLINE flatten_args_fast #-}--- | fast path flatten_args, in which none of the binders are named and--- therefore we can avoid tracking a lifting context.--- There are many bang patterns in here. It's been observed that they--- greatly improve performance of an optimized build.--- The T9872 test cases are good witnesses of this fact.-flatten_args_fast :: [TyCoBinder]- -> Kind- -> [Role]- -> [Type]- -> FlatM ([Xi], [Coercion], CoercionN)-flatten_args_fast orig_binders orig_inner_ki orig_roles orig_tys- = fmap finish (iterate orig_tys orig_roles orig_binders)- where-- iterate :: [Type]- -> [Role]- -> [TyCoBinder]- -> FlatM ([Xi], [Coercion], [TyCoBinder])- iterate (ty:tys) (role:roles) (_:binders) = do- (xi, co) <- go role ty- (xis, cos, binders) <- iterate tys roles binders- pure (xi : xis, co : cos, binders)- iterate [] _ binders = pure ([], [], binders)- iterate _ _ _ = pprPanic- "flatten_args wandered into deeper water than usual" (vcat [])- -- This debug information is commented out because leaving it in- -- causes a ~2% increase in allocations in T9872{a,c,d}.- {-- (vcat [ppr orig_binders,- ppr orig_inner_ki,- ppr (take 10 orig_roles), -- often infinite!- ppr orig_tys])- -}-- {-# INLINE go #-}- go :: Role- -> Type- -> FlatM (Xi, Coercion)- go role ty- = case role of- -- In the slow path we bind the Xi and Coercion from the recursive- -- call and then use it such- --- -- let kind_co = mkTcSymCo $ mkReflCo Nominal (tyBinderType binder)- -- casted_xi = xi `mkCastTy` kind_co- -- casted_co = xi |> kind_co ~r xi ; co- --- -- but this isn't necessary:- -- mkTcSymCo (Refl a b) = Refl a b,- -- mkCastTy x (Refl _ _) = x- -- mkTcGReflLeftCo _ ty (Refl _ _) `mkTransCo` co = co- --- -- Also, no need to check isAnonTyCoBinder or isNamedBinder, since- -- we've already established that they're all anonymous.- Nominal -> setEqRel NomEq $ flatten_one ty- Representational -> setEqRel ReprEq $ flatten_one ty- Phantom -> -- See Note [Phantoms in the flattener]- do { ty <- liftTcS $ zonkTcType ty- ; return (ty, mkReflCo Phantom ty) }--- {-# INLINE finish #-}- finish :: ([Xi], [Coercion], [TyCoBinder]) -> ([Xi], [Coercion], CoercionN)- finish (xis, cos, binders) = (xis, cos, kind_co)- where- final_kind = mkPiTys binders orig_inner_ki- kind_co = mkNomReflCo final_kind--{-# INLINE flatten_args_slow #-}--- | Slow path, compared to flatten_args_fast, because this one must track--- a lifting context.-flatten_args_slow :: [TyCoBinder] -> Kind -> TcTyCoVarSet- -> [Role] -> [Type]- -> FlatM ([Xi], [Coercion], CoercionN)-flatten_args_slow binders inner_ki fvs roles tys--- Arguments used dependently must be flattened with proper coercions, but--- we're not guaranteed to get a proper coercion when flattening with the--- "Derived" flavour. So we must call noBogusCoercions when flattening arguments--- corresponding to binders that are dependent. However, we might legitimately--- have *more* arguments than binders, in the case that the inner_ki is a variable--- that gets instantiated with a Π-type. We conservatively choose not to produce--- bogus coercions for these, too. Note that this might miss an opportunity for--- a Derived rewriting a Derived. The solution would be to generate evidence for--- Deriveds, thus avoiding this whole noBogusCoercions idea. See also--- Note [No derived kind equalities]- = do { flattened_args <- zipWith3M fl (map isNamedBinder binders ++ repeat True)- roles tys- ; return (simplifyArgsWorker binders inner_ki fvs roles flattened_args) }- where- {-# INLINE fl #-}- fl :: Bool -- must we ensure to produce a real coercion here?- -- see comment at top of function- -> Role -> Type -> FlatM (Xi, Coercion)- fl True r ty = noBogusCoercions $ fl1 r ty- fl False r ty = fl1 r ty-- {-# INLINE fl1 #-}- fl1 :: Role -> Type -> FlatM (Xi, Coercion)- fl1 Nominal ty- = setEqRel NomEq $- flatten_one ty-- fl1 Representational ty- = setEqRel ReprEq $- flatten_one ty-- fl1 Phantom ty- -- See Note [Phantoms in the flattener]- = do { ty <- liftTcS $ zonkTcType ty- ; return (ty, mkReflCo Phantom ty) }---------------------flatten_one :: TcType -> FlatM (Xi, Coercion)--- Flatten a type to get rid of type function applications, returning--- the new type-function-free type, and a collection of new equality--- constraints. See Note [Flattening] for more detail.------ Postcondition: Coercion :: Xi ~ TcType--- The role on the result coercion matches the EqRel in the FlattenEnv--flatten_one xi@(LitTy {})- = do { role <- getRole- ; return (xi, mkReflCo role xi) }--flatten_one (TyVarTy tv)- = flattenTyVar tv--flatten_one (AppTy ty1 ty2)- = flatten_app_tys ty1 [ty2]--flatten_one (TyConApp tc tys)- -- Expand type synonyms that mention type families- -- on the RHS; see Note [Flattening synonyms]- | Just (tenv, rhs, tys') <- expandSynTyCon_maybe tc tys- , let expanded_ty = mkAppTys (substTy (mkTvSubstPrs tenv) rhs) tys'- = do { mode <- getMode- ; case mode of- FM_FlattenAll | not (isFamFreeTyCon tc)- -> flatten_one expanded_ty- _ -> flatten_ty_con_app tc tys }-- -- Otherwise, it's a type function application, and we have to- -- flatten it away as well, and generate a new given equality constraint- -- between the application and a newly generated flattening skolem variable.- | isTypeFamilyTyCon tc- = flatten_fam_app tc tys-- -- For * a normal data type application- -- * data family application- -- we just recursively flatten the arguments.- | otherwise--- FM_Avoid stuff commented out; see Note [Lazy flattening]--- , let fmode' = case fmode of -- Switch off the flat_top bit in FM_Avoid--- FE { fe_mode = FM_Avoid tv _ }--- -> fmode { fe_mode = FM_Avoid tv False }--- _ -> fmode- = flatten_ty_con_app tc tys--flatten_one ty@(FunTy { ft_mult = mult, ft_arg = ty1, ft_res = ty2 })- = do { (xi1,co1) <- flatten_one ty1- ; (xi2,co2) <- flatten_one ty2- ; (xi3,co3) <- setEqRel NomEq $ flatten_one mult- ; role <- getRole- ; return (ty { ft_mult = xi3, ft_arg = xi1, ft_res = xi2 }- , mkFunCo role co3 co1 co2) }--flatten_one ty@(ForAllTy {})--- TODO (RAE): This is inadequate, as it doesn't flatten the kind of--- the bound tyvar. Doing so will require carrying around a substitution--- and the usual substTyVarBndr-like silliness. Argh.---- We allow for-alls when, but only when, no type function--- applications inside the forall involve the bound type variables.- = do { let (bndrs, rho) = tcSplitForAllTyVarBinders ty- tvs = binderVars bndrs- ; (rho', co) <- setMode FM_SubstOnly $ flatten_one rho- -- Substitute only under a forall- -- See Note [Flattening under a forall]- ; return (mkForAllTys bndrs rho', mkHomoForAllCos tvs co) }--flatten_one (CastTy ty g)- = do { (xi, co) <- flatten_one ty- ; (g', _) <- flatten_co g- ; role <- getRole- ; return (mkCastTy xi g', castCoercionKind1 co role xi ty g') }- -- It makes a /big/ difference to call castCoercionKind1 not- -- the more general castCoercionKind2.- -- See Note [castCoercionKind1] in GHC.Core.Coercion--flatten_one (CoercionTy co) = first mkCoercionTy <$> flatten_co co---- | "Flatten" a coercion. Really, just zonk it so we can uphold--- (F1) of Note [Flattening]-flatten_co :: Coercion -> FlatM (Coercion, Coercion)-flatten_co co- = do { co <- liftTcS $ zonkCo co- ; env_role <- getRole- ; let co' = mkTcReflCo env_role (mkCoercionTy co)- ; return (co, co') }---- flatten (nested) AppTys-flatten_app_tys :: Type -> [Type] -> FlatM (Xi, Coercion)--- commoning up nested applications allows us to look up the function's kind--- only once. Without commoning up like this, we would spend a quadratic amount--- of time looking up functions' types-flatten_app_tys (AppTy ty1 ty2) tys = flatten_app_tys ty1 (ty2:tys)-flatten_app_tys fun_ty arg_tys- = do { (fun_xi, fun_co) <- flatten_one fun_ty- ; flatten_app_ty_args fun_xi fun_co arg_tys }---- Given a flattened function (with the coercion produced by flattening) and--- a bunch of unflattened arguments, flatten the arguments and apply.--- The coercion argument's role matches the role stored in the FlatM monad.------ The bang patterns used here were observed to improve performance. If you--- wish to remove them, be sure to check for regeressions in allocations.-flatten_app_ty_args :: Xi -> Coercion -> [Type] -> FlatM (Xi, Coercion)-flatten_app_ty_args fun_xi fun_co []- -- this will be a common case when called from flatten_fam_app, so shortcut- = return (fun_xi, fun_co)-flatten_app_ty_args fun_xi fun_co arg_tys- = do { (xi, co, kind_co) <- case tcSplitTyConApp_maybe fun_xi of- Just (tc, xis) ->- do { let tc_roles = tyConRolesRepresentational tc- arg_roles = dropList xis tc_roles- ; (arg_xis, arg_cos, kind_co)- <- flatten_vector (tcTypeKind fun_xi) arg_roles arg_tys-- -- Here, we have fun_co :: T xi1 xi2 ~ ty- -- and we need to apply fun_co to the arg_cos. The problem is- -- that using mkAppCo is wrong because that function expects- -- its second coercion to be Nominal, and the arg_cos might- -- not be. The solution is to use transitivity:- -- T <xi1> <xi2> arg_cos ;; fun_co <arg_tys>- ; eq_rel <- getEqRel- ; let app_xi = mkTyConApp tc (xis ++ arg_xis)- app_co = case eq_rel of- NomEq -> mkAppCos fun_co arg_cos- ReprEq -> mkTcTyConAppCo Representational tc- (zipWith mkReflCo tc_roles xis ++ arg_cos)- `mkTcTransCo`- mkAppCos fun_co (map mkNomReflCo arg_tys)- ; return (app_xi, app_co, kind_co) }- Nothing ->- do { (arg_xis, arg_cos, kind_co)- <- flatten_vector (tcTypeKind fun_xi) (repeat Nominal) arg_tys- ; let arg_xi = mkAppTys fun_xi arg_xis- arg_co = mkAppCos fun_co arg_cos- ; return (arg_xi, arg_co, kind_co) }-- ; role <- getRole- ; return (homogenise_result xi co role kind_co) }--flatten_ty_con_app :: TyCon -> [TcType] -> FlatM (Xi, Coercion)-flatten_ty_con_app tc tys- = do { role <- getRole- ; (xis, cos, kind_co) <- flatten_args_tc tc (tyConRolesX role tc) tys- ; let tyconapp_xi = mkTyConApp tc xis- tyconapp_co = mkTyConAppCo role tc cos- ; return (homogenise_result tyconapp_xi tyconapp_co role kind_co) }---- Make the result of flattening homogeneous (Note [Flattening] (F2))-homogenise_result :: Xi -- a flattened type- -> Coercion -- :: xi ~r original ty- -> Role -- r- -> CoercionN -- kind_co :: tcTypeKind(xi) ~N tcTypeKind(ty)- -> (Xi, Coercion) -- (xi |> kind_co, (xi |> kind_co)- -- ~r original ty)-homogenise_result xi co r kind_co- -- the explicit pattern match here improves the performance of T9872a, b, c by- -- ~2%- | isGReflCo kind_co = (xi `mkCastTy` kind_co, co)- | otherwise = (xi `mkCastTy` kind_co- , (mkSymCo $ GRefl r xi (MCo kind_co)) `mkTransCo` co)-{-# INLINE homogenise_result #-}---- Flatten a vector (list of arguments).-flatten_vector :: Kind -- of the function being applied to these arguments- -> [Role] -- If we're flatten w.r.t. ReprEq, what roles do the- -- args have?- -> [Type] -- the args to flatten- -> FlatM ([Xi], [Coercion], CoercionN)-flatten_vector ki roles tys- = do { eq_rel <- getEqRel- ; case eq_rel of- NomEq -> flatten_args bndrs- any_named_bndrs- inner_ki- fvs- (repeat Nominal)- tys- ReprEq -> flatten_args bndrs- any_named_bndrs- inner_ki- fvs- roles- tys- }- where- (bndrs, inner_ki, any_named_bndrs) = split_pi_tys' ki- fvs = tyCoVarsOfType ki-{-# INLINE flatten_vector #-}--{--Note [Flattening synonyms]-~~~~~~~~~~~~~~~~~~~~~~~~~~-Not expanding synonyms aggressively improves error messages, and-keeps types smaller. But we need to take care.--Suppose- type T a = a -> a-and we want to flatten the type (T (F a)). Then we can safely flatten-the (F a) to a skolem, and return (T fsk). We don't need to expand the-synonym. This works because TcTyConAppCo can deal with synonyms-(unlike TyConAppCo), see Note [TcCoercions] in GHC.Tc.Types.Evidence.--But (#8979) for- type T a = (F a, a) where F is a type function-we must expand the synonym in (say) T Int, to expose the type function-to the flattener.---Note [Flattening under a forall]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Under a forall, we- (a) MUST apply the inert substitution- (b) MUST NOT flatten type family applications-Hence FMSubstOnly.--For (a) consider c ~ a, a ~ T (forall b. (b, [c]))-If we don't apply the c~a substitution to the second constraint-we won't see the occurs-check error.--For (b) consider (a ~ forall b. F a b), we don't want to flatten-to (a ~ forall b.fsk, F a b ~ fsk)-because now the 'b' has escaped its scope. We'd have to flatten to- (a ~ forall b. fsk b, forall b. F a b ~ fsk b)-and we have not begun to think about how to make that work!--************************************************************************-* *- Flattening a type-family application-* *-************************************************************************--}--flatten_fam_app :: TyCon -> [TcType] -> FlatM (Xi, Coercion)- -- flatten_fam_app can be over-saturated- -- flatten_exact_fam_app is exactly saturated- -- flatten_exact_fam_app_fully lifts out the application to top level- -- Postcondition: Coercion :: Xi ~ F tys-flatten_fam_app tc tys -- Can be over-saturated- = ASSERT2( tys `lengthAtLeast` tyConArity tc- , ppr tc $$ ppr (tyConArity tc) $$ ppr tys)-- do { mode <- getMode- ; case mode of- { FM_SubstOnly -> flatten_ty_con_app tc tys- ; FM_FlattenAll ->-- -- Type functions are saturated- -- The type function might be *over* saturated- -- in which case the remaining arguments should- -- be dealt with by AppTys- do { let (tys1, tys_rest) = splitAt (tyConArity tc) tys- ; (xi1, co1) <- flatten_exact_fam_app_fully tc tys1- -- co1 :: xi1 ~ F tys1-- ; flatten_app_ty_args xi1 co1 tys_rest } } }---- the [TcType] exactly saturate the TyCon--- See note [flatten_exact_fam_app_fully performance]-flatten_exact_fam_app_fully :: TyCon -> [TcType] -> FlatM (Xi, Coercion)-flatten_exact_fam_app_fully tc tys- -- See Note [Reduce type family applications eagerly]- -- the following tcTypeKind should never be evaluated, as it's just used in- -- casting, and casts by refl are dropped- = do { mOut <- try_to_reduce_nocache tc tys- ; case mOut of- Just out -> pure out- Nothing -> do- { -- First, flatten the arguments- ; (xis, cos, kind_co)- <- setEqRel NomEq $ -- just do this once, instead of for- -- each arg- flatten_args_tc tc (repeat Nominal) tys- -- kind_co :: tcTypeKind(F xis) ~N tcTypeKind(F tys)- ; eq_rel <- getEqRel- ; cur_flav <- getFlavour- ; let role = eqRelRole eq_rel- ret_co = mkTyConAppCo role tc cos- -- ret_co :: F xis ~ F tys; might be heterogeneous-- -- Now, look in the cache- ; mb_ct <- liftTcS $ lookupFlatCache tc xis- ; case mb_ct of- Just (co, rhs_ty, flav) -- co :: F xis ~ fsk- -- flav is [G] or [WD]- -- See Note [Type family equations] in GHC.Tc.Solver.Monad- | (NotSwapped, _) <- flav `funEqCanDischargeF` cur_flav- -> -- Usable hit in the flat-cache- do { traceFlat "flatten/flat-cache hit" $- (ppr tc <+> ppr xis $$ ppr rhs_ty)- ; (fsk_xi, fsk_co) <- flatten_one rhs_ty- -- The fsk may already have been unified, so- -- flatten it- -- fsk_co :: fsk_xi ~ fsk- ; let xi = fsk_xi `mkCastTy` kind_co- co' = mkTcCoherenceLeftCo role fsk_xi kind_co fsk_co- `mkTransCo`- maybeTcSubCo eq_rel (mkSymCo co)- `mkTransCo` ret_co- ; return (xi, co')- }- -- :: fsk_xi ~ F xis-- -- Try to reduce the family application right now- -- See Note [Reduce type family applications eagerly]- _ -> do { mOut <- try_to_reduce tc- xis- kind_co- (`mkTransCo` ret_co)- ; case mOut of- Just out -> pure out- Nothing -> do- { loc <- getLoc- ; (ev, co, fsk) <- liftTcS $- newFlattenSkolem cur_flav loc tc xis-- -- The new constraint (F xis ~ fsk) is not- -- necessarily inert (e.g. the LHS may be a- -- redex) so we must put it in the work list- ; let ct = CFunEqCan { cc_ev = ev- , cc_fun = tc- , cc_tyargs = xis- , cc_fsk = fsk }- ; emitFlatWork ct-- ; traceFlat "flatten/flat-cache miss" $- (ppr tc <+> ppr xis $$ ppr fsk $$ ppr ev)-- -- NB: fsk's kind is already flattened because- -- the xis are flattened- ; let fsk_ty = mkTyVarTy fsk- xi = fsk_ty `mkCastTy` kind_co- co' = mkTcCoherenceLeftCo role fsk_ty kind_co (maybeTcSubCo eq_rel (mkSymCo co))- `mkTransCo` ret_co- ; return (xi, co')- }- }- }- }-- where-- -- try_to_reduce and try_to_reduce_nocache (below) could be unified into- -- a more general definition, but it was observed that separating them- -- gives better performance (lower allocation numbers in T9872x).-- try_to_reduce :: TyCon -- F, family tycon- -> [Type] -- args, not necessarily flattened- -> CoercionN -- kind_co :: tcTypeKind(F args) ~N- -- tcTypeKind(F orig_args)- -- where- -- orig_args is what was passed to the outer- -- function- -> ( Coercion -- :: (xi |> kind_co) ~ F args- -> Coercion ) -- what to return from outer function- -> FlatM (Maybe (Xi, Coercion))- try_to_reduce tc tys kind_co update_co- = do { checkStackDepth (mkTyConApp tc tys)- ; mb_match <- liftTcS $ matchFam tc tys- ; case mb_match of- -- NB: norm_co will always be homogeneous. All type families- -- are homogeneous.- Just (norm_co, norm_ty)- -> do { traceFlat "Eager T.F. reduction success" $- vcat [ ppr tc, ppr tys, ppr norm_ty- , ppr norm_co <+> dcolon- <+> ppr (coercionKind norm_co)- ]- ; (xi, final_co) <- bumpDepth $ flatten_one norm_ty- ; eq_rel <- getEqRel- ; let co = maybeTcSubCo eq_rel norm_co- `mkTransCo` mkSymCo final_co- ; flavour <- getFlavour- -- NB: only extend cache with nominal equalities- ; when (eq_rel == NomEq) $- liftTcS $- extendFlatCache tc tys ( co, xi, flavour )- ; let role = eqRelRole eq_rel- xi' = xi `mkCastTy` kind_co- co' = update_co $- mkTcCoherenceLeftCo role xi kind_co (mkSymCo co)- ; return $ Just (xi', co') }- Nothing -> pure Nothing }-- try_to_reduce_nocache :: TyCon -- F, family tycon- -> [Type] -- args, not necessarily flattened- -> FlatM (Maybe (Xi, Coercion))- try_to_reduce_nocache tc tys- = do { checkStackDepth (mkTyConApp tc tys)- ; mb_match <- liftTcS $ matchFam tc tys- ; case mb_match of- -- NB: norm_co will always be homogeneous. All type families- -- are homogeneous.- Just (norm_co, norm_ty)- -> do { (xi, final_co) <- bumpDepth $ flatten_one norm_ty- ; eq_rel <- getEqRel- ; let co = mkSymCo (maybeTcSubCo eq_rel norm_co- `mkTransCo` mkSymCo final_co)- ; return $ Just (xi, co) }- Nothing -> pure Nothing }--{- Note [Reduce type family applications eagerly]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-If we come across a type-family application like (Append (Cons x Nil) t),-then, rather than flattening to a skolem etc, we may as well just reduce-it on the spot to (Cons x t). This saves a lot of intermediate steps.-Examples that are helped are tests T9872, and T5321Fun.--Performance testing indicates that it's best to try this *twice*, once-before flattening arguments and once after flattening arguments.-Adding the extra reduction attempt before flattening arguments cut-the allocation amounts for the T9872{a,b,c} tests by half.--An example of where the early reduction appears helpful:-- type family Last x where- Last '[x] = x- Last (h ': t) = Last t-- workitem: (x ~ Last '[1,2,3,4,5,6])--Flattening the argument never gets us anywhere, but trying to flatten-it at every step is quadratic in the length of the list. Reducing more-eagerly makes simplifying the right-hand type linear in its length.--Testing also indicated that the early reduction should *not* use the-flat-cache, but that the later reduction *should*. (Although the-effect was not large.) Hence the Bool argument to try_to_reduce. To-me (SLPJ) this seems odd; I get that eager reduction usually succeeds;-and if don't use the cache for eager reduction, we will miss most of-the opportunities for using it at all. More exploration would be good-here.--At the end, once we've got a flat rhs, we extend the flatten-cache to record-the result. Doing so can save lots of work when the same redex shows up more-than once. Note that we record the link from the redex all the way to its-*final* value, not just the single step reduction. Interestingly, using the-flat-cache for the first reduction resulted in an increase in allocations-of about 3% for the four T9872x tests. However, using the flat-cache in-the later reduction is a similar gain. I (Richard E) don't currently (Dec '14)-have any knowledge as to *why* these facts are true.--************************************************************************-* *- Flattening a type variable-* *-********************************************************************* -}---- | The result of flattening a tyvar "one step".-data FlattenTvResult- = FTRNotFollowed- -- ^ The inert set doesn't make the tyvar equal to anything else-- | FTRFollowed TcType Coercion- -- ^ The tyvar flattens to a not-necessarily flat other type.- -- co :: new type ~r old type, where the role is determined by- -- the FlattenEnv--flattenTyVar :: TyVar -> FlatM (Xi, Coercion)-flattenTyVar tv- = do { mb_yes <- flatten_tyvar1 tv- ; case mb_yes of- FTRFollowed ty1 co1 -- Recur- -> do { (ty2, co2) <- flatten_one ty1- -- ; traceFlat "flattenTyVar2" (ppr tv $$ ppr ty2)- ; return (ty2, co2 `mkTransCo` co1) }-- FTRNotFollowed -- Done, but make sure the kind is zonked- -- Note [Flattening] invariant (F0) and (F1)- -> do { tv' <- liftTcS $ updateTyVarKindM zonkTcType tv- ; role <- getRole- ; let ty' = mkTyVarTy tv'- ; return (ty', mkTcReflCo role ty') } }--flatten_tyvar1 :: TcTyVar -> FlatM FlattenTvResult--- "Flattening" a type variable means to apply the substitution to it--- Specifically, look up the tyvar in--- * the internal MetaTyVar box--- * the inerts--- See also the documentation for FlattenTvResult--flatten_tyvar1 tv- = do { mb_ty <- liftTcS $ isFilledMetaTyVar_maybe tv- ; case mb_ty of- Just ty -> do { traceFlat "Following filled tyvar"- (ppr tv <+> equals <+> ppr ty)- ; role <- getRole- ; return (FTRFollowed ty (mkReflCo role ty)) } ;- Nothing -> do { traceFlat "Unfilled tyvar" (pprTyVar tv)- ; fr <- getFlavourRole- ; flatten_tyvar2 tv fr } }--flatten_tyvar2 :: TcTyVar -> CtFlavourRole -> FlatM FlattenTvResult--- The tyvar is not a filled-in meta-tyvar--- Try in the inert equalities--- See Definition [Applying a generalised substitution] in GHC.Tc.Solver.Monad--- See Note [Stability of flattening] in GHC.Tc.Solver.Monad--flatten_tyvar2 tv fr@(_, eq_rel)- = do { ieqs <- liftTcS $ getInertEqs- ; mode <- getMode- ; case lookupDVarEnv ieqs tv of- Just (ct:_) -- If the first doesn't work,- -- the subsequent ones won't either- | CTyEqCan { cc_ev = ctev, cc_tyvar = tv- , cc_rhs = rhs_ty, cc_eq_rel = ct_eq_rel } <- ct- , let ct_fr = (ctEvFlavour ctev, ct_eq_rel)- , ct_fr `eqCanRewriteFR` fr -- This is THE key call of eqCanRewriteFR- -> do { traceFlat "Following inert tyvar"- (ppr mode <+>- ppr tv <+>- equals <+>- ppr rhs_ty $$ ppr ctev)- ; let rewrite_co1 = mkSymCo (ctEvCoercion ctev)- rewrite_co = case (ct_eq_rel, eq_rel) of- (ReprEq, _rel) -> ASSERT( _rel == ReprEq )- -- if this ASSERT fails, then- -- eqCanRewriteFR answered incorrectly- rewrite_co1- (NomEq, NomEq) -> rewrite_co1- (NomEq, ReprEq) -> mkSubCo rewrite_co1-- ; return (FTRFollowed rhs_ty rewrite_co) }- -- NB: ct is Derived then fmode must be also, hence- -- we are not going to touch the returned coercion- -- so ctEvCoercion is fine.-- _other -> return FTRNotFollowed }--{--Note [An alternative story for the inert substitution]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-(This entire note is just background, left here in case we ever want- to return the previous state of affairs)--We used (GHC 7.8) to have this story for the inert substitution inert_eqs-- * 'a' is not in fvs(ty)- * They are *inert* in the weaker sense that there is no infinite chain of- (i1 `eqCanRewrite` i2), (i2 `eqCanRewrite` i3), etc--This means that flattening must be recursive, but it does allow- [G] a ~ [b]- [G] b ~ Maybe c--This avoids "saturating" the Givens, which can save a modest amount of work.-It is easy to implement, in GHC.Tc.Solver.Interact.kick_out, by only kicking out an inert-only if (a) the work item can rewrite the inert AND- (b) the inert cannot rewrite the work item--This is significantly harder to think about. It can save a LOT of work-in occurs-check cases, but we don't care about them much. #5837-is an example; all the constraints here are Givens-- [G] a ~ TF (a,Int)- -->- work TF (a,Int) ~ fsk- inert fsk ~ a-- --->- work fsk ~ (TF a, TF Int)- inert fsk ~ a-- --->- work a ~ (TF a, TF Int)- inert fsk ~ a-- ---> (attempting to flatten (TF a) so that it does not mention a- work TF a ~ fsk2- inert a ~ (fsk2, TF Int)- inert fsk ~ (fsk2, TF Int)-- ---> (substitute for a)- work TF (fsk2, TF Int) ~ fsk2- inert a ~ (fsk2, TF Int)- inert fsk ~ (fsk2, TF Int)-- ---> (top-level reduction, re-orient)- work fsk2 ~ (TF fsk2, TF Int)- inert a ~ (fsk2, TF Int)- inert fsk ~ (fsk2, TF Int)-- ---> (attempt to flatten (TF fsk2) to get rid of fsk2- work TF fsk2 ~ fsk3- work fsk2 ~ (fsk3, TF Int)- inert a ~ (fsk2, TF Int)- inert fsk ~ (fsk2, TF Int)-- --->- work TF fsk2 ~ fsk3- inert fsk2 ~ (fsk3, TF Int)- inert a ~ ((fsk3, TF Int), TF Int)- inert fsk ~ ((fsk3, TF Int), TF Int)--Because the incoming given rewrites all the inert givens, we get more and-more duplication in the inert set. But this really only happens in pathological-casee, so we don't care.---************************************************************************-* *- Unflattening-* *-************************************************************************--An unflattening example:- [W] F a ~ alpha-flattens to- [W] F a ~ fmv (CFunEqCan)- [W] fmv ~ alpha (CTyEqCan)-We must solve both!--}--unflattenWanteds :: Cts -> Cts -> TcS Cts-unflattenWanteds tv_eqs funeqs- = do { tclvl <- getTcLevel-- ; traceTcS "Unflattening" $ braces $- vcat [ text "Funeqs =" <+> pprCts funeqs- , text "Tv eqs =" <+> pprCts tv_eqs ]-- -- Step 1: unflatten the CFunEqCans, except if that causes an occurs check- -- Occurs check: consider [W] alpha ~ [F alpha]- -- ==> (flatten) [W] F alpha ~ fmv, [W] alpha ~ [fmv]- -- ==> (unify) [W] F [fmv] ~ fmv- -- See Note [Unflatten using funeqs first]- ; funeqs <- foldrM unflatten_funeq emptyCts funeqs- ; traceTcS "Unflattening 1" $ braces (pprCts funeqs)-- -- Step 2: unify the tv_eqs, if possible- ; tv_eqs <- foldrM (unflatten_eq tclvl) emptyCts tv_eqs- ; traceTcS "Unflattening 2" $ braces (pprCts tv_eqs)-- -- Step 3: fill any remaining fmvs with fresh unification variables- ; funeqs <- mapBagM finalise_funeq funeqs- ; traceTcS "Unflattening 3" $ braces (pprCts funeqs)-- -- Step 4: remove any tv_eqs that look like ty ~ ty- ; tv_eqs <- foldrM finalise_eq emptyCts tv_eqs-- ; let all_flat = tv_eqs `andCts` funeqs- ; traceTcS "Unflattening done" $ braces (pprCts all_flat)-- ; return all_flat }- where- ----------------- unflatten_funeq :: Ct -> Cts -> TcS Cts- unflatten_funeq ct@(CFunEqCan { cc_fun = tc, cc_tyargs = xis- , cc_fsk = fmv, cc_ev = ev }) rest- = do { -- fmv should be an un-filled flatten meta-tv;- -- we now fix its final value by filling it, being careful- -- to observe the occurs check. Zonking will eliminate it- -- altogether in due course- rhs' <- zonkTcType (mkTyConApp tc xis)- ; case occCheckExpand [fmv] rhs' of- Just rhs'' -- Normal case: fill the tyvar- -> do { setReflEvidence ev NomEq rhs''- ; unflattenFmv fmv rhs''- ; return rest }-- Nothing -> -- Occurs check- return (ct `consCts` rest) }-- unflatten_funeq other_ct _- = pprPanic "unflatten_funeq" (ppr other_ct)-- ----------------- finalise_funeq :: Ct -> TcS Ct- finalise_funeq (CFunEqCan { cc_fsk = fmv, cc_ev = ev })- = do { demoteUnfilledFmv fmv- ; return (mkNonCanonical ev) }- finalise_funeq ct = pprPanic "finalise_funeq" (ppr ct)-- ----------------- unflatten_eq :: TcLevel -> Ct -> Cts -> TcS Cts- unflatten_eq tclvl ct@(CTyEqCan { cc_ev = ev, cc_tyvar = tv- , cc_rhs = rhs, cc_eq_rel = eq_rel }) rest-- | NomEq <- eq_rel -- See Note [Do not unify representational equalities]- -- in GHC.Tc.Solver.Interact- , isFmvTyVar tv -- Previously these fmvs were untouchable,- -- but now they are touchable- -- NB: unlike unflattenFmv, filling a fmv here /does/- -- bump the unification count; it is "improvement"- -- Note [Unflattening can force the solver to iterate]- = ASSERT2( tyVarKind tv `eqType` tcTypeKind rhs, ppr ct )- -- CTyEqCan invariant (TyEq:K) should ensure this is true- do { is_filled <- isFilledMetaTyVar tv- ; elim <- case is_filled of- False -> do { traceTcS "unflatten_eq 2" (ppr ct)- ; tryFill ev tv rhs }- True -> do { traceTcS "unflatten_eq 3" (ppr ct)- ; try_fill_rhs ev tclvl tv rhs }- ; if elim- then do { setReflEvidence ev eq_rel (mkTyVarTy tv)- ; return rest }- else return (ct `consCts` rest) }-- | otherwise- = return (ct `consCts` rest)-- unflatten_eq _ ct _ = pprPanic "unflatten_irred" (ppr ct)-- ----------------- try_fill_rhs ev tclvl lhs_tv rhs- -- Constraint is lhs_tv ~ rhs_tv,- -- and lhs_tv is filled, so try RHS- | Just (rhs_tv, co) <- getCastedTyVar_maybe rhs- -- co :: kind(rhs_tv) ~ kind(lhs_tv)- , isFmvTyVar rhs_tv || (isTouchableMetaTyVar tclvl rhs_tv- && not (isTyVarTyVar rhs_tv))- -- LHS is a filled fmv, and so is a type- -- family application, which a TyVarTv should- -- not unify with- = do { is_filled <- isFilledMetaTyVar rhs_tv- ; if is_filled then return False- else tryFill ev rhs_tv- (mkTyVarTy lhs_tv `mkCastTy` mkSymCo co) }-- | otherwise- = return False-- ----------------- finalise_eq :: Ct -> Cts -> TcS Cts- finalise_eq (CTyEqCan { cc_ev = ev, cc_tyvar = tv- , cc_rhs = rhs, cc_eq_rel = eq_rel }) rest- | isFmvTyVar tv- = do { ty1 <- zonkTcTyVar tv- ; rhs' <- zonkTcType rhs- ; if ty1 `tcEqType` rhs'- then do { setReflEvidence ev eq_rel rhs'- ; return rest }- else return (mkNonCanonical ev `consCts` rest) }-- | otherwise- = return (mkNonCanonical ev `consCts` rest)-- finalise_eq ct _ = pprPanic "finalise_irred" (ppr ct)--tryFill :: CtEvidence -> TcTyVar -> TcType -> TcS Bool--- (tryFill tv rhs ev) assumes 'tv' is an /un-filled/ MetaTv--- If tv does not appear in 'rhs', it set tv := rhs,--- binds the evidence (which should be a CtWanted) to Refl<rhs>--- and return True. Otherwise returns False-tryFill ev tv rhs- = ASSERT2( not (isGiven ev), ppr ev )- do { rhs' <- zonkTcType rhs- ; case () of- _ | Just tv' <- tcGetTyVar_maybe rhs'- , tv == tv' -- tv == rhs- -> return True-- _ | Just rhs'' <- occCheckExpand [tv] rhs'- -> do { -- Fill the tyvar- unifyTyVar tv rhs''- ; return True }-- _ | otherwise -- Occurs check- -> return False- }--setReflEvidence :: CtEvidence -> EqRel -> TcType -> TcS ()-setReflEvidence ev eq_rel rhs- = setEvBindIfWanted ev (evCoercion refl_co)- where- refl_co = mkTcReflCo (eqRelRole eq_rel) rhs--{--Note [Unflatten using funeqs first]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~- [W] G a ~ Int- [W] F (G a) ~ G a--do not want to end up with- [W] F Int ~ Int-because that might actually hold! Better to end up with the two above-unsolved constraints. The flat form will be-- G a ~ fmv1 (CFunEqCan)- F fmv1 ~ fmv2 (CFunEqCan)- fmv1 ~ Int (CTyEqCan)- fmv1 ~ fmv2 (CTyEqCan)--Flatten using the fun-eqs first.--}---- | Like 'splitPiTys'' but comes with a 'Bool' which is 'True' iff there is at--- least one named binder.-split_pi_tys' :: Type -> ([TyCoBinder], Type, Bool)-split_pi_tys' ty = split ty ty- where- -- put common cases first- split _ (ForAllTy b res) = let (bs, ty, _) = split res res- in (Named b : bs, ty, True)- split _ (FunTy { ft_af = af, ft_mult = w, ft_arg = arg, ft_res = res })- = let (bs, ty, named) = split res res- in (Anon af (mkScaled w arg) : bs, ty, named)-- split orig_ty ty | Just ty' <- coreView ty = split orig_ty ty'- split orig_ty _ = ([], orig_ty, False)-{-# INLINE split_pi_tys' #-}---- | Like 'tyConBindersTyCoBinders' but you also get a 'Bool' which is true iff--- there is at least one named binder.-ty_con_binders_ty_binders' :: [TyConBinder] -> ([TyCoBinder], Bool)-ty_con_binders_ty_binders' = foldr go ([], False)- where- go (Bndr tv (NamedTCB vis)) (bndrs, _)- = (Named (Bndr tv vis) : bndrs, True)- go (Bndr tv (AnonTCB af)) (bndrs, n)- = (Anon af (unrestricted (tyVarKind tv)) : bndrs, n)- {-# INLINE go #-}-{-# INLINE ty_con_binders_ty_binders' #-}
compiler/GHC/Tc/Solver/Interact.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP, MultiWayIf #-} {-# OPTIONS_GHC -Wno-incomplete-record-updates #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}@@ -11,14 +11,11 @@ #include "GhclibHsVersions.h" import GHC.Prelude-import GHC.Types.Basic ( SwapFlag(..), isSwapped,+import GHC.Types.Basic ( SwapFlag(..), infinity, IntWithInf, intGtLimit ) import GHC.Tc.Solver.Canonical-import GHC.Tc.Solver.Flatten-import GHC.Tc.Utils.Unify ( canSolveByUnification ) import GHC.Types.Var.Set import GHC.Core.Type as Type-import GHC.Core.Coercion ( BlockSubstFlag(..) ) import GHC.Core.InstEnv ( DFunInstType ) import GHC.Types.Var@@ -41,6 +38,7 @@ import GHC.Tc.Types.Constraint import GHC.Core.Predicate import GHC.Tc.Types.Origin+import GHC.Tc.Utils.TcMType( promoteMetaTyVarTo ) import GHC.Tc.Solver.Monad import GHC.Data.Bag import GHC.Utils.Monad ( concatMapM, foldlM )@@ -57,6 +55,7 @@ import GHC.Driver.Session import GHC.Utils.Misc import qualified GHC.LanguageExtensions as LangExt+import Data.List.NonEmpty ( NonEmpty(..) ) import Control.Monad.Trans.Class import Control.Monad.Trans.Maybe@@ -90,50 +89,6 @@ If in Step 1 no such element exists, we have exceeded our context-stack depth and will simply fail.--Note [Unflatten after solving the simple wanteds]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We unflatten after solving the wc_simples of an implication, and before attempting-to float. This means that-- * The fsk/fmv flatten-skolems only survive during solveSimples. We don't- need to worry about them across successive passes over the constraint tree.- (E.g. we don't need the old ic_fsk field of an implication.-- * When floating an equality outwards, we don't need to worry about floating its- associated flattening constraints.-- * Another tricky case becomes easy: #4935- type instance F True a b = a- type instance F False a b = b-- [w] F c a b ~ gamma- (c ~ True) => a ~ gamma- (c ~ False) => b ~ gamma-- Obviously this is soluble with gamma := F c a b, and unflattening- will do exactly that after solving the simple constraints and before- attempting the implications. Before, when we were not unflattening,- we had to push Wanted funeqs in as new givens. Yuk!-- Another example that becomes easy: indexed_types/should_fail/T7786- [W] BuriedUnder sub k Empty ~ fsk- [W] Intersect fsk inv ~ s- [w] xxx[1] ~ s- [W] forall[2] . (xxx[1] ~ Empty)- => Intersect (BuriedUnder sub k Empty) inv ~ Empty--Note [Running plugins on unflattened wanteds]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-There is an annoying mismatch between solveSimpleGivens and-solveSimpleWanteds, because the latter needs to fiddle with the inert-set, unflatten and zonk the wanteds. It passes the zonked wanteds-to runTcPluginsWanteds, which produces a replacement set of wanteds,-some additional insolubles and a flag indicating whether to go round-the loop again. If so, prepareInertsForImplications is used to remove-the previous wanteds (which will still be in the inert set). Note-that prepareInertsForImplications will discard the insolubles, so we-must keep track of them separately. -} solveSimpleGivens :: [Ct] -> TcS ()@@ -151,8 +106,6 @@ go new_givens } solveSimpleWanteds :: Cts -> TcS WantedConstraints--- NB: 'simples' may contain /derived/ equalities, floated--- out from a nested implication. So don't discard deriveds! -- The result is not necessarily zonked solveSimpleWanteds simples = do { traceTcS "solveSimpleWanteds {" (ppr simples)@@ -177,48 +130,36 @@ | otherwise = do { -- Solve- (unif_count, wc1) <- solve_simple_wanteds wc+ wc1 <- solve_simple_wanteds wc -- Run plugins ; (rerun_plugin, wc2) <- runTcPluginsWanted wc1- -- See Note [Running plugins on unflattened wanteds] - ; if unif_count == 0 && not rerun_plugin- then return (n, wc2) -- Done- else do { traceTcS "solveSimple going round again:" $- ppr unif_count $$ ppr rerun_plugin- ; go (n+1) limit wc2 } } -- Loop+ ; if rerun_plugin+ then do { traceTcS "solveSimple going round again:" (ppr rerun_plugin)+ ; go (n+1) limit wc2 } -- Loop+ else return (n, wc2) } -- Done -solve_simple_wanteds :: WantedConstraints -> TcS (Int, WantedConstraints)+solve_simple_wanteds :: WantedConstraints -> TcS WantedConstraints -- Try solving these constraints -- Affects the unification state (of course) but not the inert set -- The result is not necessarily zonked solve_simple_wanteds (WC { wc_simple = simples1, wc_impl = implics1, wc_holes = holes }) = nestTcS $ do { solveSimples simples1- ; (implics2, tv_eqs, fun_eqs, others) <- getUnsolvedInerts- ; (unif_count, unflattened_eqs) <- reportUnifications $- unflattenWanteds tv_eqs fun_eqs- -- See Note [Unflatten after solving the simple wanteds]- ; return ( unif_count- , WC { wc_simple = others `andCts` unflattened_eqs- , wc_impl = implics1 `unionBags` implics2- , wc_holes = holes }) }+ ; (implics2, unsolved) <- getUnsolvedInerts+ ; return (WC { wc_simple = unsolved+ , wc_impl = implics1 `unionBags` implics2+ , wc_holes = holes }) } {- Note [The solveSimpleWanteds loop] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Solving a bunch of simple constraints is done in a loop, (the 'go' loop of 'solveSimpleWanteds'):- 1. Try to solve them; unflattening may lead to improvement that- was not exploitable during solving+ 1. Try to solve them 2. Try the plugin- 3. If step 1 did improvement during unflattening; or if the plugin- wants to run again, go back to step 1--Non-obviously, improvement can also take place during-the unflattening that takes place in step (1). See GHC.Tc.Solver.Flatten,-See Note [Unflattening can force the solver to iterate]+ 3. If the plugin wants to run again, go back to step 1 -} -- The main solver loop implements Note [Basic Simplifier Plan]@@ -258,7 +199,7 @@ ; updInertIrreds (\irreds -> extendCtsList irreds insols) ; return (pluginNewCts p) } } } --- | Given a bag of (flattened, zonked) wanteds, invoke the plugins on+-- | Given a bag of (rewritten, zonked) wanteds, invoke the plugins on -- them and produce an updated bag of wanteds (possibly with some new -- work) and a bag of insolubles. The boolean indicates whether -- 'solveSimpleWanteds' should feed the updated wanteds back into the@@ -481,17 +422,17 @@ -- Interaction result of WorkItem <~> Ct interactWithInertsStage :: WorkItem -> TcS (StopOrContinue Ct)--- Precondition: if the workitem is a CTyEqCan then it will not be able to--- react with anything at this stage.+-- Precondition: if the workitem is a CEqCan then it will not be able to+-- react with anything at this stage (except, maybe, via a type family+-- dependency) interactWithInertsStage wi = do { inerts <- getTcSInerts ; let ics = inert_cans inerts ; case wi of- CTyEqCan {} -> interactTyVarEq ics wi- CFunEqCan {} -> interactFunEq ics wi- CIrredCan {} -> interactIrred ics wi- CDictCan {} -> interactDict ics wi+ CEqCan {} -> interactEq ics wi+ CIrredCan {} -> interactIrred ics wi+ CDictCan {} -> interactDict ics wi _ -> pprPanic "interactWithInerts" (ppr wi) } -- CNonCanonical have been canonicalised @@ -790,25 +731,26 @@ Assume we have started with an implication: - forall c. Eq c => { wc_simple = D [c] c [W] }+ forall c. Eq c => { wc_simple = [W] D [c] c } -which we have simplified to:+which we have simplified to, with a Derived constraing coming from+D's functional dependency: - forall c. Eq c => { wc_simple = D [c] c [W]- (c ~ [c]) [D] }+ forall c. Eq c => { wc_simple = [W] D [c] c [W]+ [D] (c ~ [c]) } -For some reason, e.g. because we floated an equality somewhere else,-we might try to re-solve this implication. If we do not do a-dropDerivedWC, then we will end up trying to solve the following-constraints the second time:+When iterating the solver, we might try to re-solve this+implication. If we do not do a dropDerivedWC, then we will end up+trying to solve the following constraints the second time: - (D [c] c) [W]- (c ~ [c]) [D]+ [W] (D [c] c)+ [D] (c ~ [c]) which will result in two Deriveds to end up in the insoluble set: - wc_simple = D [c] c [W]- (c ~ [c]) [D], (c ~ [c]) [D]+ wc_simple = [W] D [c] c+ [D] (c ~ [c])+ [D] (c ~ [c]) -} {-@@ -918,7 +860,7 @@ instance {-# OVERLAPPABLE #-} (Take (n - 1)) => Take n where .. And we have [W] Take 3. That only matches one instance so we get-[W] Take (3-1). Really we should now flatten to reduce the (3-1) to 2, and+[W] Take (3-1). Really we should now rewrite to reduce the (3-1) to 2, and so on -- but that is reproducing yet more of the solver. Sigh. For now, we just give up (remember all this is just an optimisation). @@ -1127,7 +1069,9 @@ ; lift $ traceTcS "shortCutSolver: found instance" (ppr preds) ; loc' <- lift $ checkInstanceOK loc what pred+ ; lift $ checkReductionDepth loc' pred + ; evc_vs <- mapM (new_wanted_cached loc' solved_dicts') preds -- Emit work for subgoals but use our local cache -- so we can solve recursive dictionaries.@@ -1298,113 +1242,63 @@ ********************************************************************** -} -interactFunEq :: InertCans -> Ct -> TcS (StopOrContinue Ct)--- Try interacting the work item with the inert set-interactFunEq inerts work_item@(CFunEqCan { cc_ev = ev, cc_fun = tc- , cc_tyargs = args, cc_fsk = fsk })- | Just inert_ct@(CFunEqCan { cc_ev = ev_i- , cc_fsk = fsk_i })- <- findFunEq (inert_funeqs inerts) tc args- , pr@(swap_flag, upgrade_flag) <- ev_i `funEqCanDischarge` ev- = do { traceTcS "reactFunEq (rewrite inert item):" $- vcat [ text "work_item =" <+> ppr work_item- , text "inertItem=" <+> ppr ev_i- , text "(swap_flag, upgrade)" <+> ppr pr ]- ; if isSwapped swap_flag- then do { -- Rewrite inert using work-item- let work_item' | upgrade_flag = upgradeWanted work_item- | otherwise = work_item- ; updInertFunEqs $ \ feqs -> insertFunEq feqs tc args work_item'- -- Do the updInertFunEqs before the reactFunEq, so that- -- we don't kick out the inertItem as well as consuming it!- ; reactFunEq ev fsk ev_i fsk_i- ; stopWith ev "Work item rewrites inert" }- else do { -- Rewrite work-item using inert- ; when upgrade_flag $- updInertFunEqs $ \ feqs -> insertFunEq feqs tc args- (upgradeWanted inert_ct)- ; reactFunEq ev_i fsk_i ev fsk- ; stopWith ev "Inert rewrites work item" } }-- | otherwise -- Try improvement- = do { improveLocalFunEqs ev inerts tc args fsk- ; continueWith work_item }--interactFunEq _ work_item = pprPanic "interactFunEq" (ppr work_item)--upgradeWanted :: Ct -> Ct--- We are combining a [W] F tys ~ fmv1 and [D] F tys ~ fmv2--- so upgrade the [W] to [WD] before putting it in the inert set-upgradeWanted ct = ct { cc_ev = upgrade_ev (cc_ev ct) }- where- upgrade_ev ev = ASSERT2( isWanted ev, ppr ct )- ev { ctev_nosh = WDeriv }--improveLocalFunEqs :: CtEvidence -> InertCans -> TyCon -> [TcType] -> TcTyVar+improveLocalFunEqs :: CtEvidence -> InertCans -> TyCon -> [TcType] -> TcType -> TcS () -- Generate derived improvement equalities, by comparing -- the current work item with inert CFunEqs -- E.g. x + y ~ z, x + y' ~ z => [D] y ~ y' -- -- See Note [FunDep and implicit parameter reactions]-improveLocalFunEqs work_ev inerts fam_tc args fsk- | isGiven work_ev -- See Note [No FunEq improvement for Givens]- || not (isImprovable work_ev)- = return ()-- | otherwise- = do { eqns <- improvement_eqns- ; if not (null eqns)- then do { traceTcS "interactFunEq improvements: " $- vcat [ text "Eqns:" <+> ppr eqns+-- Precondition: isImprovable work_ev+improveLocalFunEqs work_ev inerts fam_tc args rhs+ = ASSERT( isImprovable work_ev )+ unless (null improvement_eqns) $+ do { traceTcS "interactFunEq improvements: " $+ vcat [ text "Eqns:" <+> ppr improvement_eqns , text "Candidates:" <+> ppr funeqs_for_tc , text "Inert eqs:" <+> ppr (inert_eqs inerts) ]- ; emitFunDepDeriveds eqns }- else return () }-+ ; emitFunDepDeriveds improvement_eqns } where funeqs = inert_funeqs inerts- funeqs_for_tc = findFunEqsByTyCon funeqs fam_tc+ funeqs_for_tc = [ funeq_ct | EqualCtList (funeq_ct :| _)+ <- findFunEqsByTyCon funeqs fam_tc+ , NomEq == ctEqRel funeq_ct ]+ -- representational equalities don't interact+ -- with type family dependencies work_loc = ctEvLoc work_ev work_pred = ctEvPred work_ev fam_inj_info = tyConInjectivityInfo fam_tc --------------------- improvement_eqns :: TcS [FunDepEqn CtLoc]+ improvement_eqns :: [FunDepEqn CtLoc] improvement_eqns | Just ops <- isBuiltInSynFamTyCon_maybe fam_tc = -- Try built-in families, notably for arithmethic- do { rhs <- rewriteTyVar fsk- ; concatMapM (do_one_built_in ops rhs) funeqs_for_tc }+ concatMap (do_one_built_in ops rhs) funeqs_for_tc | Injective injective_args <- fam_inj_info = -- Try improvement from type families with injectivity annotations- do { rhs <- rewriteTyVar fsk- ; concatMapM (do_one_injective injective_args rhs) funeqs_for_tc }+ concatMap (do_one_injective injective_args rhs) funeqs_for_tc | otherwise- = return []+ = [] --------------------- do_one_built_in ops rhs (CFunEqCan { cc_tyargs = iargs, cc_fsk = ifsk, cc_ev = inert_ev })- = do { inert_rhs <- rewriteTyVar ifsk- ; return $ mk_fd_eqns inert_ev (sfInteractInert ops args rhs iargs inert_rhs) }+ do_one_built_in ops rhs (CEqCan { cc_lhs = TyFamLHS _ iargs, cc_rhs = irhs, cc_ev = inert_ev })+ = mk_fd_eqns inert_ev (sfInteractInert ops args rhs iargs irhs) do_one_built_in _ _ _ = pprPanic "interactFunEq 1" (ppr fam_tc) -------------------- -- See Note [Type inference for type families with injectivity]- do_one_injective inj_args rhs (CFunEqCan { cc_tyargs = inert_args- , cc_fsk = ifsk, cc_ev = inert_ev })+ do_one_injective inj_args rhs (CEqCan { cc_lhs = TyFamLHS _ inert_args+ , cc_rhs = irhs, cc_ev = inert_ev }) | isImprovable inert_ev- = do { inert_rhs <- rewriteTyVar ifsk- ; return $ if rhs `tcEqType` inert_rhs- then mk_fd_eqns inert_ev $- [ Pair arg iarg- | (arg, iarg, True) <- zip3 args inert_args inj_args ]- else [] }+ , rhs `tcEqType` irhs+ = mk_fd_eqns inert_ev $ [ Pair arg iarg+ | (arg, iarg, True) <- zip3 args inert_args inj_args ] | otherwise- = return []+ = [] do_one_injective _ _ _ = pprPanic "interactFunEq 2" (ppr fam_tc) @@ -1421,26 +1315,13 @@ loc = inert_loc { ctl_depth = ctl_depth inert_loc `maxSubGoalDepth` ctl_depth work_loc } ---------------reactFunEq :: CtEvidence -> TcTyVar -- From this :: F args1 ~ fsk1- -> CtEvidence -> TcTyVar -- Solve this :: F args2 ~ fsk2- -> TcS ()-reactFunEq from_this fsk1 solve_this fsk2- = do { traceTcS "reactFunEq"- (vcat [ppr from_this, ppr fsk1, ppr solve_this, ppr fsk2])- ; dischargeFunEq solve_this fsk2 (ctEvCoercion from_this) (mkTyVarTy fsk1)- ; traceTcS "reactFunEq done" (ppr from_this $$ ppr fsk1 $$- ppr solve_this $$ ppr fsk2) }- {- Note [Type inference for type families with injectivity]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Suppose we have a type family with an injectivity annotation: type family F a b = r | r -> b -Then if we have two CFunEqCan constraints for F with the same RHS- F s1 t1 ~ rhs- F s2 t2 ~ rhs-then we can use the injectivity to get a new Derived constraint on+Then if we have an equality like F s1 t1 ~ F s2 t2,+we can use the injectivity to get a new Derived constraint on the injective argument [D] t1 ~ t2 @@ -1467,9 +1348,21 @@ applications, but that would require new evidence forms, and an extension to FC, so we don't do that right now (Dec 14). -See also Note [Injective type families] in GHC.Core.TyCon+We generate these Deriveds in three places, depending on how we notice the+injectivity. +1. When we have a [W/D] F tys1 ~ F tys2. This is handled in canEqCanLHS2, and+described in Note [Decomposing equality] in GHC.Tc.Solver.Canonical. +2. When we have [W] F tys1 ~ T and [W] F tys2 ~ T. Note that neither of these+constraints rewrites the other, as they have different LHSs. This is done+in improveLocalFunEqs, called during the interactWithInertsStage.++3. When we have [W] F tys ~ T and an equation for F that looks like F tys' = T.+This is done in improve_top_fun_eqs, called from the top-level reactions stage.++See also Note [Injective type families] in GHC.Core.TyCon+ Note [Cache-caused loops] ~~~~~~~~~~~~~~~~~~~~~~~~~ It is very dangerous to cache a rewritten wanted family equation as 'solved' in our@@ -1501,85 +1394,34 @@ just an optimization so we don't lose anything in terms of completeness of solving. --Note [Efficient Orientation]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we are interacting two FunEqCans with the same LHS:- (inert) ci :: (F ty ~ xi_i)- (work) cw :: (F ty ~ xi_w)-We prefer to keep the inert (else we pass the work item on down-the pipeline, which is a bit silly). If we keep the inert, we-will (a) discharge 'cw'- (b) produce a new equality work-item (xi_w ~ xi_i)-Notice the orientation (xi_w ~ xi_i) NOT (xi_i ~ xi_w):- new_work :: xi_w ~ xi_i- cw := ci ; sym new_work-Why? Consider the simplest case when xi1 is a type variable. If-we generate xi1~xi2, processing that constraint will kick out 'ci'.-If we generate xi2~xi1, there is less chance of that happening.-Of course it can and should still happen if xi1=a, xi1=Int, say.-But we want to avoid it happening needlessly.--Similarly, if we *can't* keep the inert item (because inert is Wanted,-and work is Given, say), we prefer to orient the new equality (xi_i ~-xi_w).--Note [Carefully solve the right CFunEqCan]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~- ---- OLD COMMENT, NOW NOT NEEDED- ---- because we now allow multiple- ---- wanted FunEqs with the same head-Consider the constraints- c1 :: F Int ~ a -- Arising from an application line 5- c2 :: F Int ~ Bool -- Arising from an application line 10-Suppose that 'a' is a unification variable, arising only from-flattening. So there is no error on line 5; it's just a flattening-variable. But there is (or might be) an error on line 10.--Two ways to combine them, leaving either (Plan A)- c1 :: F Int ~ a -- Arising from an application line 5- c3 :: a ~ Bool -- Arising from an application line 10-or (Plan B)- c2 :: F Int ~ Bool -- Arising from an application line 10- c4 :: a ~ Bool -- Arising from an application line 5--Plan A will unify c3, leaving c1 :: F Int ~ Bool as an error-on the *totally innocent* line 5. An example is test SimpleFail16-where the expected/actual message comes out backwards if we use-the wrong plan.--The second is the right thing to do. Hence the isMetaTyVarTy-test when solving pairwise CFunEqCan.-- ********************************************************************** * *- interactTyVarEq+ interactEq * * ********************************************************************** -} -inertsCanDischarge :: InertCans -> TcTyVar -> TcType -> CtFlavourRole+inertsCanDischarge :: InertCans -> CanEqLHS -> TcType -> CtFlavourRole -> Maybe ( CtEvidence -- The evidence for the inert , SwapFlag -- Whether we need mkSymCo , Bool) -- True <=> keep a [D] version -- of the [WD] constraint-inertsCanDischarge inerts tv rhs fr- | (ev_i : _) <- [ ev_i | CTyEqCan { cc_ev = ev_i, cc_rhs = rhs_i- , cc_eq_rel = eq_rel }- <- findTyEqs inerts tv+inertsCanDischarge inerts lhs rhs fr+ | (ev_i : _) <- [ ev_i | CEqCan { cc_ev = ev_i, cc_rhs = rhs_i+ , cc_eq_rel = eq_rel }+ <- findEq inerts lhs , (ctEvFlavour ev_i, eq_rel) `eqCanDischargeFR` fr , rhs_i `tcEqType` rhs ] = -- Inert: a ~ ty -- Work item: a ~ ty Just (ev_i, NotSwapped, keep_deriv ev_i) - | Just tv_rhs <- getTyVar_maybe rhs- , (ev_i : _) <- [ ev_i | CTyEqCan { cc_ev = ev_i, cc_rhs = rhs_i- , cc_eq_rel = eq_rel }- <- findTyEqs inerts tv_rhs+ | Just rhs_lhs <- canEqLHS_maybe rhs+ , (ev_i : _) <- [ ev_i | CEqCan { cc_ev = ev_i, cc_rhs = rhs_i+ , cc_eq_rel = eq_rel }+ <- findEq inerts rhs_lhs , (ctEvFlavour ev_i, eq_rel) `eqCanDischargeFR` fr- , rhs_i `tcEqType` mkTyVarTy tv ]+ , rhs_i `tcEqType` canEqLHSType lhs ] = -- Inert: a ~ b -- Work item: b ~ a Just (ev_i, IsSwapped, keep_deriv ev_i)@@ -1595,16 +1437,15 @@ | otherwise = False -- Work item is fully discharged -interactTyVarEq :: InertCans -> Ct -> TcS (StopOrContinue Ct)--- CTyEqCans are always consumed, so always returns Stop-interactTyVarEq inerts workItem@(CTyEqCan { cc_tyvar = tv- , cc_rhs = rhs- , cc_ev = ev- , cc_eq_rel = eq_rel })+interactEq :: InertCans -> Ct -> TcS (StopOrContinue Ct)+interactEq inerts workItem@(CEqCan { cc_lhs = lhs+ , cc_rhs = rhs+ , cc_ev = ev+ , cc_eq_rel = eq_rel }) | Just (ev_i, swapped, keep_deriv)- <- inertsCanDischarge inerts tv rhs (ctEvFlavour ev, eq_rel)+ <- inertsCanDischarge inerts lhs rhs (ctEvFlavour ev, eq_rel) = do { setEvBindIfWanted ev $- evCoercion (maybeSym swapped $+ evCoercion (maybeTcSymCo swapped $ tcDowngradeRole (eqRelRole eq_rel) (ctEvRole ev_i) (ctEvCoercion ev_i))@@ -1622,21 +1463,43 @@ = do { traceTcS "Not unifying representational equality" (ppr workItem) ; continueWith workItem } - | isGiven ev -- See Note [Touchables and givens]- = continueWith workItem- | otherwise- = do { tclvl <- getTcLevel- ; if canSolveByUnification tclvl tv rhs- then do { solveByUnification ev tv rhs- ; n_kicked <- kickOutAfterUnification tv- ; return (Stop ev (text "Solved by unification" <+> pprKicked n_kicked)) }+ = case lhs of+ TyVarLHS tv -> tryToSolveByUnification workItem ev tv rhs - else continueWith workItem }+ TyFamLHS tc args -> do { when (isImprovable ev) $+ -- Try improvement, if possible+ improveLocalFunEqs ev inerts tc args rhs+ ; continueWith workItem } -interactTyVarEq _ wi = pprPanic "interactTyVarEq" (ppr wi)+interactEq _ wi = pprPanic "interactEq" (ppr wi) -solveByUnification :: CtEvidence -> TcTyVar -> Xi -> TcS ()+----------------------+-- We have a meta-tyvar on the left, and metaTyVarUpateOK has said "yes"+-- So try to solve by unifying.+-- Three reasons why not:+-- Skolem escape+-- Given equalities (GADTs)+-- Unifying a TyVarTv with a non-tyvar type+tryToSolveByUnification :: Ct -> CtEvidence+ -> TcTyVar -- LHS tyvar+ -> TcType -- RHS+ -> TcS (StopOrContinue Ct)+tryToSolveByUnification work_item ev tv rhs+ = do { can_unify <- unifyTest ev tv rhs+ ; traceTcS "tryToSolveByUnification" (vcat [ ppr tv <+> char '~' <+> ppr rhs+ , ppr can_unify ])++ ; case can_unify of+ NoUnify -> continueWith work_item+ -- For the latter two cases see Note [Solve by unification]+ UnifySameLevel -> solveByUnification ev tv rhs+ UnifyOuterLevel free_metas tv_lvl+ -> do { wrapTcS $ mapM_ (promoteMetaTyVarTo tv_lvl) free_metas+ ; setUnificationFlag tv_lvl+ ; solveByUnification ev tv rhs } }++solveByUnification :: CtEvidence -> TcTyVar -> Xi -> TcS (StopOrContinue Ct) -- Solve with the identity coercion -- Precondition: kind(xi) equals kind(tv) -- Precondition: CtEvidence is Wanted or Derived@@ -1645,7 +1508,7 @@ -- workItem = the new Given constraint -- -- NB: No need for an occurs check here, because solveByUnification always--- arises from a CTyEqCan, a *canonical* constraint. Its invariant (TyEq:OC)+-- arises from a CEqCan, a *canonical* constraint. Its invariant (TyEq:OC) -- says that in (a ~ xi), the type variable a does not appear in xi. -- See GHC.Tc.Types.Constraint.Ct invariants. --@@ -1658,9 +1521,10 @@ text "Coercion:" <+> pprEq tv_ty xi, text "Left Kind is:" <+> ppr (tcTypeKind tv_ty), text "Right Kind is:" <+> ppr (tcTypeKind xi) ]- ; unifyTyVar tv xi- ; setEvBindIfWanted wd (evCoercion (mkTcNomReflCo xi)) }+ ; setEvBindIfWanted wd (evCoercion (mkTcNomReflCo xi))+ ; n_kicked <- kickOutAfterUnification tv+ ; return (Stop wd (text "Solved by unification" <+> pprKicked n_kicked)) } {- Note [Avoid double unifications] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -1694,9 +1558,37 @@ and we want to get alpha := N b. See also #15144, which was caused by unifying a representational-equality (in the unflattener).+equality. +Note [Solve by unification]+~~~~~~~~~~~~~~~~~~~~~~~~~~~+If we solve+ alpha[n] ~ ty+by unification, there are two cases to consider +* UnifySameLevel: if the ambient level is 'n', then+ we can simply update alpha := ty, and do nothing else++* UnifyOuterLevel free_metas n: if the ambient level is greater than+ 'n' (the level of alpha), in addition to setting alpha := ty we must+ do two other things:++ 1. Promote all the free meta-vars of 'ty' to level n. After all,+ alpha[n] is at level n, and so if we set, say,+ alpha[n] := Maybe beta[m],+ we must ensure that when unifying beta we do skolem-escape checks+ etc relevent to level n. Simple way to do that: promote beta to+ level n.++ 2. Set the Unification Level Flag to record that a level-n unification has+ taken place. See Note [The Unification Level Flag] in GHC.Tc.Solver.Monad++NB: UnifySameLevel is just an optimisation for UnifyOuterLevel. Promotion+would be a no-op, and setting the unification flag unnecessarily would just+make the solver iterate more often. (We don't need to iterate when unifying+at the ambient level becuase of the kick-out mechanism.)++ ************************************************************************ * * * Functional dependencies, instantiation of equations@@ -1822,9 +1714,8 @@ ; case work_item of CDictCan {} -> do { inerts <- getTcSInerts ; doTopReactDict inerts work_item }- CFunEqCan {} -> doTopReactFunEq work_item+ CEqCan {} -> doTopReactEq work_item CIrredCan {} -> doTopReactOther work_item- CTyEqCan {} -> doTopReactOther work_item _ -> -- Any other work item does not react with any top-level equations continueWith work_item } @@ -1832,7 +1723,7 @@ -------------------- doTopReactOther :: Ct -> TcS (StopOrContinue Ct) -- Try local quantified constraints for--- CTyEqCan e.g. (a ~# ty)+-- CEqCan e.g. (lhs ~# ty) -- and CIrredCan e.g. (c a) -- -- Why equalities? See GHC.Tc.Solver.Canonical@@ -1889,126 +1780,24 @@ * Note [Evidence for quantified constraints] in GHC.Core.Predicate * Note [Equality superclasses in quantified constraints] in GHC.Tc.Solver.Canonical--Note [Flatten when discharging CFunEqCan]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We have the following scenario (#16512):--type family LV (as :: [Type]) (b :: Type) = (r :: Type) | r -> as b where- LV (a ': as) b = a -> LV as b--[WD] w1 :: LV as0 (a -> b) ~ fmv1 (CFunEqCan)-[WD] w2 :: fmv1 ~ (a -> fmv2) (CTyEqCan)-[WD] w3 :: LV as0 b ~ fmv2 (CFunEqCan)--We start with w1. Because LV is injective, we wish to see if the RHS of the-equation matches the RHS of the CFunEqCan. The RHS of a CFunEqCan is always an-fmv, so we "look through" to get (a -> fmv2). Then we run tcUnifyTyWithTFs.-That performs the match, but it allows a type family application (such as the-LV in the RHS of the equation) to match with anything. (See "Injective type-families" by Stolarek et al., HS'15, Fig. 2) The matching succeeds, which-means we can improve as0 (and b, but that's not interesting here). However,-because the RHS of w1 can't see through fmv2 (we have no way of looking up a-LHS of a CFunEqCan from its RHS, and this use case isn't compelling enough),-we invent a new unification variable here. We thus get (as0 := a : as1).-Rewriting:--[WD] w1 :: LV (a : as1) (a -> b) ~ fmv1-[WD] w2 :: fmv1 ~ (a -> fmv2)-[WD] w3 :: LV (a : as1) b ~ fmv2--We can now reduce both CFunEqCans, using the equation for LV. We get--[WD] w2 :: (a -> LV as1 (a -> b)) ~ (a -> a -> LV as1 b)--Now we decompose (and flatten) to--[WD] w4 :: LV as1 (a -> b) ~ fmv3-[WD] w5 :: fmv3 ~ (a -> fmv1)-[WD] w6 :: LV as1 b ~ fmv4--which is exactly where we started. These goals really are insoluble, but-we would prefer not to loop. We thus need to find a way to bump the reduction-depth, so that we can detect the loop and abort.--The key observation is that we are performing a reduction. We thus wish-to bump the level when discharging a CFunEqCan. Where does this bumped-level go, though? It can't just go on the reduct, as that's a type. Instead,-it must go on any CFunEqCans produced after flattening. We thus flatten-when discharging, making sure that the level is bumped in the new-fun-eqs. The flattening happens in reduce_top_fun_eq and the level-is bumped when setting up the FlatM monad in GHC.Tc.Solver.Flatten.runFlatten.-(This bumping will happen for call sites other than this one, but that-makes sense -- any constraints emitted by the flattener are offshoots-the work item and should have a higher level. We don't have any test-cases that require the bumping in this other cases, but it's convenient-and causes no harm to bump at every flatten.)--Test case: typecheck/should_fail/T16512a- -} ---------------------doTopReactFunEq :: Ct -> TcS (StopOrContinue Ct)-doTopReactFunEq work_item@(CFunEqCan { cc_ev = old_ev, cc_fun = fam_tc- , cc_tyargs = args, cc_fsk = fsk })-- | fsk `elemVarSet` tyCoVarsOfTypes args- = no_reduction -- See Note [FunEq occurs-check principle]-- | otherwise -- Note [Reduction for Derived CFunEqCans]- = do { match_res <- matchFam fam_tc args- -- Look up in top-level instances, or built-in axiom- -- See Note [MATCHING-SYNONYMS]- ; case match_res of- Nothing -> no_reduction- Just match_info -> reduce_top_fun_eq old_ev fsk match_info }- where- no_reduction- = do { improveTopFunEqs old_ev fam_tc args fsk- ; continueWith work_item }--doTopReactFunEq w = pprPanic "doTopReactFunEq" (ppr w)--reduce_top_fun_eq :: CtEvidence -> TcTyVar -> (TcCoercion, TcType)- -> TcS (StopOrContinue Ct)--- We have found an applicable top-level axiom: use it to reduce--- Precondition: fsk is not free in rhs_ty--- ax_co :: F tys ~ rhs_ty, where F tys is the LHS of the old_ev-reduce_top_fun_eq old_ev fsk (ax_co, rhs_ty)- | not (isDerived old_ev) -- Precondition of shortCutReduction- , Just (tc, tc_args) <- tcSplitTyConApp_maybe rhs_ty- , isTypeFamilyTyCon tc- , tc_args `lengthIs` tyConArity tc -- Short-cut- = -- RHS is another type-family application- -- Try shortcut; see Note [Top-level reductions for type functions]- do { shortCutReduction old_ev fsk ax_co tc tc_args- ; stopWith old_ev "Fun/Top (shortcut)" }-- | otherwise- = ASSERT2( not (fsk `elemVarSet` tyCoVarsOfType rhs_ty)- , ppr old_ev $$ ppr rhs_ty )- -- Guaranteed by Note [FunEq occurs-check principle]- do { (rhs_xi, flatten_co) <- flatten FM_FlattenAll old_ev rhs_ty- -- flatten_co :: rhs_xi ~ rhs_ty- -- See Note [Flatten when discharging CFunEqCan]- ; let total_co = ax_co `mkTcTransCo` mkTcSymCo flatten_co- ; dischargeFunEq old_ev fsk total_co rhs_xi- ; traceTcS "doTopReactFunEq" $- vcat [ text "old_ev:" <+> ppr old_ev- , nest 2 (text ":=") <+> ppr ax_co ]- ; stopWith old_ev "Fun/Top" }+doTopReactEq :: Ct -> TcS (StopOrContinue Ct)+doTopReactEq work_item@(CEqCan { cc_ev = old_ev, cc_lhs = TyFamLHS fam_tc args+ , cc_rhs = rhs })+ = do { improveTopFunEqs old_ev fam_tc args rhs+ ; doTopReactOther work_item }+doTopReactEq work_item = doTopReactOther work_item -improveTopFunEqs :: CtEvidence -> TyCon -> [TcType] -> TcTyVar -> TcS ()+improveTopFunEqs :: CtEvidence -> TyCon -> [TcType] -> TcType -> TcS () -- See Note [FunDep and implicit parameter reactions]-improveTopFunEqs ev fam_tc args fsk- | isGiven ev -- See Note [No FunEq improvement for Givens]- || not (isImprovable ev)+improveTopFunEqs ev fam_tc args rhs+ | not (isImprovable ev) = return () | otherwise = do { fam_envs <- getFamInstEnvs- ; rhs <- rewriteTyVar fsk ; eqns <- improve_top_fun_eqs fam_envs fam_tc args rhs ; traceTcS "improveTopFunEqs" (vcat [ ppr fam_tc <+> ppr args <+> ppr rhs , ppr eqns ])@@ -2090,127 +1879,7 @@ _ -> True , (ax_arg, arg, True) <- zip3 ax_args args inj_args ] } --shortCutReduction :: CtEvidence -> TcTyVar -> TcCoercion- -> TyCon -> [TcType] -> TcS ()--- See Note [Top-level reductions for type functions]--- Previously, we flattened the tc_args here, but there's no need to do so.--- And, if we did, this function would have all the complication of--- GHC.Tc.Solver.Canonical.canCFunEqCan. See Note [canCFunEqCan]-shortCutReduction old_ev fsk ax_co fam_tc tc_args- = ASSERT( ctEvEqRel old_ev == NomEq)- -- ax_co :: F args ~ G tc_args- -- old_ev :: F args ~ fsk- do { new_ev <- case ctEvFlavour old_ev of- Given -> newGivenEvVar deeper_loc- ( mkPrimEqPred (mkTyConApp fam_tc tc_args) (mkTyVarTy fsk)- , evCoercion (mkTcSymCo ax_co- `mkTcTransCo` ctEvCoercion old_ev) )-- Wanted {} ->- -- See TcCanonical Note [Equalities with incompatible kinds] about NoBlockSubst- do { (new_ev, new_co) <- newWantedEq_SI NoBlockSubst WDeriv deeper_loc Nominal- (mkTyConApp fam_tc tc_args) (mkTyVarTy fsk)- ; setWantedEq (ctev_dest old_ev) $ ax_co `mkTcTransCo` new_co- ; return new_ev }-- Derived -> pprPanic "shortCutReduction" (ppr old_ev)-- ; let new_ct = CFunEqCan { cc_ev = new_ev, cc_fun = fam_tc- , cc_tyargs = tc_args, cc_fsk = fsk }- ; updWorkListTcS (extendWorkListFunEq new_ct) }- where- deeper_loc = bumpCtLocDepth (ctEvLoc old_ev)--{- Note [Top-level reductions for type functions]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-c.f. Note [The flattening story] in GHC.Tc.Solver.Flatten--Suppose we have a CFunEqCan F tys ~ fmv/fsk, and a matching axiom.-Here is what we do, in four cases:--* Wanteds: general firing rule- (work item) [W] x : F tys ~ fmv- instantiate axiom: ax_co : F tys ~ rhs-- Then:- Discharge fmv := rhs- Discharge x := ax_co ; sym x2- This is *the* way that fmv's get unified; even though they are- "untouchable".-- NB: Given Note [FunEq occurs-check principle], fmv does not appear- in tys, and hence does not appear in the instantiated RHS. So- the unification can't make an infinite type.--* Wanteds: short cut firing rule- Applies when the RHS of the axiom is another type-function application- (work item) [W] x : F tys ~ fmv- instantiate axiom: ax_co : F tys ~ G rhs_tys-- It would be a waste to create yet another fmv for (G rhs_tys).- Instead (shortCutReduction):- - Flatten rhs_tys (cos : rhs_tys ~ rhs_xis)- - Add G rhs_xis ~ fmv to flat cache (note: the same old fmv)- - New canonical wanted [W] x2 : G rhs_xis ~ fmv (CFunEqCan)- - Discharge x := ax_co ; G cos ; x2--* Givens: general firing rule- (work item) [G] g : F tys ~ fsk- instantiate axiom: ax_co : F tys ~ rhs-- Now add non-canonical given (since rhs is not flat)- [G] (sym g ; ax_co) : fsk ~ rhs (Non-canonical)--* Givens: short cut firing rule- Applies when the RHS of the axiom is another type-function application- (work item) [G] g : F tys ~ fsk- instantiate axiom: ax_co : F tys ~ G rhs_tys-- It would be a waste to create yet another fsk for (G rhs_tys).- Instead (shortCutReduction):- - Flatten rhs_tys: flat_cos : tys ~ flat_tys- - Add new Canonical given- [G] (sym (G flat_cos) ; co ; g) : G flat_tys ~ fsk (CFunEqCan)--Note [FunEq occurs-check principle]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-I have spent a lot of time finding a good way to deal with-CFunEqCan constraints like- F (fuv, a) ~ fuv-where flatten-skolem occurs on the LHS. Now in principle we-might may progress by doing a reduction, but in practice its-hard to find examples where it is useful, and easy to find examples-where we fall into an infinite reduction loop. A rule that works-very well is this:-- *** FunEq occurs-check principle ***-- Do not reduce a CFunEqCan- F tys ~ fsk- if fsk appears free in tys- Instead we treat it as stuck.--Examples:--* #5837 has [G] a ~ TF (a,Int), with an instance- type instance TF (a,b) = (TF a, TF b)- This readily loops when solving givens. But with the FunEq occurs- check principle, it rapidly gets stuck which is fine.--* #12444 is a good example, explained in comment:2. We have- type instance F (Succ x) = Succ (F x)- [W] alpha ~ Succ (F alpha)- If we allow the reduction to happen, we get an infinite loop--Note [Cached solved FunEqs]-~~~~~~~~~~~~~~~~~~~~~~~~~~~-When trying to solve, say (FunExpensive big-type ~ ty), it's important-to see if we have reduced (FunExpensive big-type) before, lest we-simply repeat it. Hence the lookup in inert_solved_funeqs. Moreover-we must use `funEqCanDischarge` because both uses might (say) be Wanteds,-and we *still* want to save the re-computation.-+{- Note [MATCHING-SYNONYMS] ~~~~~~~~~~~~~~~~~~~~~~~~ When trying to match a dictionary (D tau) to a top-level instance, or a@@ -2254,68 +1923,6 @@ handle it. Instead we are careful to orient the new derived equality with the template on the left. Delicate, but it works. -Note [No FunEq improvement for Givens]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We don't do improvements (injectivity etc) for Givens. Why?--* It generates Derived constraints on skolems, which don't do us- much good, except perhaps identify inaccessible branches.- (They'd be perfectly valid though.)--* For type-nat stuff the derived constraints include type families;- e.g. (a < b), (b < c) ==> a < c If we generate a Derived for this,- we'll generate a Derived/Wanted CFunEqCan; and, since the same- InertCans (after solving Givens) are used for each iteration, that- massively confused the unflattening step (GHC.Tc.Solver.Flatten.unflatten).-- In fact it led to some infinite loops:- indexed-types/should_compile/T10806- indexed-types/should_compile/T10507- polykinds/T10742--Note [Reduction for Derived CFunEqCans]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-You may wonder if it's important to use top-level instances to-simplify [D] CFunEqCan's. But it is. Here's an example (T10226).-- type instance F Int = Int- type instance FInv Int = Int--Suppose we have to solve- [WD] FInv (F alpha) ~ alpha- [WD] F alpha ~ Int-- --> flatten- [WD] F alpha ~ fuv0- [WD] FInv fuv0 ~ fuv1 -- (A)- [WD] fuv1 ~ alpha- [WD] fuv0 ~ Int -- (B)-- --> Rewwrite (A) with (B), splitting it- [WD] F alpha ~ fuv0- [W] FInv fuv0 ~ fuv1- [D] FInv Int ~ fuv1 -- (C)- [WD] fuv1 ~ alpha- [WD] fuv0 ~ Int-- --> Reduce (C) with top-level instance- **** This is the key step ***- [WD] F alpha ~ fuv0- [W] FInv fuv0 ~ fuv1- [D] fuv1 ~ Int -- (D)- [WD] fuv1 ~ alpha -- (E)- [WD] fuv0 ~ Int-- --> Rewrite (D) with (E)- [WD] F alpha ~ fuv0- [W] FInv fuv0 ~ fuv1- [D] alpha ~ Int -- (F)- [WD] fuv1 ~ alpha- [WD] fuv0 ~ Int-- --> unify (F) alpha := Int, and that solves it--Another example is indexed-types/should_compile/T10634 -} {- *******************************************************************@@ -2379,47 +1986,48 @@ , cir_mk_ev = mk_ev }) = do { traceTcS "doTopReact/found instance for" $ ppr ev ; deeper_loc <- checkInstanceOK loc what pred- ; if isDerived ev then finish_derived deeper_loc theta- else finish_wanted deeper_loc theta mk_ev }+ ; if isDerived ev+ then -- Use type-class instances for Deriveds, in the hope+ -- of generating some improvements+ -- C.f. Example 3 of Note [The improvement story]+ -- It's easy because no evidence is involved+ do { dflags <- getDynFlags+ ; unless (subGoalDepthExceeded dflags (ctLocDepth deeper_loc)) $+ emitNewDeriveds deeper_loc theta+ -- If we have a runaway Derived, let's not issue a+ -- "reduction stack overflow" error, which is not particularly+ -- friendly. Instead, just drop the Derived.+ ; traceTcS "finish_derived" (ppr (ctl_depth deeper_loc))+ ; stopWith ev "Dict/Top (solved derived)" }++ else -- wanted+ do { checkReductionDepth deeper_loc pred+ ; evb <- getTcEvBindsVar+ ; if isCoEvBindsVar evb+ then continueWith work_item+ -- See Note [Instances in no-evidence implications]++ else+ do { evc_vars <- mapM (newWanted deeper_loc) theta+ ; setEvBindIfWanted ev (mk_ev (map getEvExpr evc_vars))+ ; emitWorkNC (freshGoals evc_vars)+ ; stopWith ev "Dict/Top (solved wanted)" }}} where ev = ctEvidence work_item pred = ctEvPred ev loc = ctEvLoc ev - finish_wanted :: CtLoc -> [TcPredType]- -> ([EvExpr] -> EvTerm) -> TcS (StopOrContinue Ct)- -- Precondition: evidence term matches the predicate workItem- finish_wanted loc theta mk_ev- = do { evb <- getTcEvBindsVar- ; if isCoEvBindsVar evb- then -- See Note [Instances in no-evidence implications]- continueWith work_item- else- do { evc_vars <- mapM (newWanted loc) theta- ; setEvBindIfWanted ev (mk_ev (map getEvExpr evc_vars))- ; emitWorkNC (freshGoals evc_vars)- ; stopWith ev "Dict/Top (solved wanted)" } }-- finish_derived loc theta- = -- Use type-class instances for Deriveds, in the hope- -- of generating some improvements- -- C.f. Example 3 of Note [The improvement story]- -- It's easy because no evidence is involved- do { emitNewDeriveds loc theta- ; traceTcS "finish_derived" (ppr (ctl_depth loc))- ; stopWith ev "Dict/Top (solved derived)" }- chooseInstance work_item lookup_res = pprPanic "chooseInstance" (ppr work_item $$ ppr lookup_res) checkInstanceOK :: CtLoc -> InstanceWhat -> TcPredType -> TcS CtLoc -- Check that it's OK to use this insstance: -- (a) the use is well staged in the Template Haskell sense--- (b) we have not recursed too deep -- Returns the CtLoc to used for sub-goals+-- Probably also want to call checkReductionDepth, but this function+-- does not do so to enable special handling for Deriveds in chooseInstance checkInstanceOK loc what pred = do { checkWellStagedDFun loc what pred- ; checkReductionDepth deeper_loc pred ; return deeper_loc } where deeper_loc = zap_origin (bumpCtLocDepth loc)@@ -2460,7 +2068,7 @@ -- First check whether there is an in-scope Given that could -- match this constraint. In that case, do not use any instance -- whether top level, or local quantified constraints.--- ee Note [Instance and Given overlap]+-- See Note [Instance and Given overlap] | not (xopt LangExt.IncoherentInstances dflags) , not (naturallyCoherentClass clas) , let matchable_givens = matchableGivens loc pred inerts@@ -2533,7 +2141,7 @@ The end effect is that, much as we do for overlapping instances, we delay choosing a class instance if there is a possibility of another instance OR a given to match our constraint later on. This fixes-#4981 and #5002.+tickets #4981 and #5002. Other notes: @@ -2543,12 +2151,7 @@ - natural numbers - Typeable -* Flatten-skolems: we do not treat a flatten-skolem as unifiable- for this purpose.- E.g. f :: Eq (F a) => [a] -> [a]- f xs = ....(xs==xs).....- Here we get [W] Eq [a], and we don't want to refrain from solving- it because of the given (Eq (F a)) constraint!+* See also Note [What might match later?] in GHC.Tc.Solver.Monad. * 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
@@ -1,3662 +1,3786 @@-{-# LANGUAGE CPP, DeriveFunctor, TypeFamilies #-}--{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}---- | Type definitions for the constraint solver-module GHC.Tc.Solver.Monad (-- -- The work list- WorkList(..), isEmptyWorkList, emptyWorkList,- extendWorkListNonEq, extendWorkListCt,- extendWorkListCts, extendWorkListEq, extendWorkListFunEq,- appendWorkList,- selectNextWorkItem,- workListSize, workListWantedCount,- getWorkList, updWorkListTcS, pushLevelNoWorkList,-- -- The TcS monad- TcS, runTcS, runTcSDeriveds, runTcSWithEvBinds, runTcSInerts,- failTcS, warnTcS, addErrTcS,- runTcSEqualities,- nestTcS, nestImplicTcS, setEvBindsTcS,- emitImplicationTcS, emitTvImplicationTcS,-- runTcPluginTcS, addUsedGRE, addUsedGREs, keepAlive,- matchGlobalInst, TcM.ClsInstResult(..),-- QCInst(..),-- -- Tracing etc- panicTcS, traceTcS,- traceFireTcS, bumpStepCountTcS, csTraceTcS,- wrapErrTcS, wrapWarnTcS,-- -- Evidence creation and transformation- MaybeNew(..), freshGoals, isFresh, getEvExpr,-- newTcEvBinds, newNoTcEvBinds,- newWantedEq, newWantedEq_SI, emitNewWantedEq,- newWanted, newWanted_SI, newWantedEvVar,- newWantedNC, newWantedEvVarNC,- newDerivedNC,- newBoundEvVarId,- unifyTyVar, unflattenFmv, reportUnifications,- setEvBind, setWantedEq,- setWantedEvTerm, setEvBindIfWanted,- newEvVar, newGivenEvVar, newGivenEvVars,- emitNewDeriveds, emitNewDerivedEq,- checkReductionDepth,- getSolvedDicts, setSolvedDicts,-- getInstEnvs, getFamInstEnvs, -- Getting the environments- getTopEnv, getGblEnv, getLclEnv,- getTcEvBindsVar, getTcLevel,- getTcEvTyCoVars, getTcEvBindsMap, setTcEvBindsMap,- tcLookupClass, tcLookupId,-- -- Inerts- InertSet(..), InertCans(..), emptyInert,- updInertTcS, updInertCans, updInertDicts, updInertIrreds,- getNoGivenEqs, setInertCans,- getInertEqs, getInertCans, getInertGivens,- getInertInsols,- getTcSInerts, setTcSInerts,- matchableGivens, prohibitedSuperClassSolve, mightMatchLater,- getUnsolvedInerts,- removeInertCts, getPendingGivenScs,- addInertCan, insertFunEq, addInertForAll,- emitWorkNC, emitWork,- isImprovable,-- -- The Model- kickOutAfterUnification,-- -- Inert Safe Haskell safe-overlap failures- addInertSafehask, insertSafeOverlapFailureTcS, updInertSafehask,- getSafeOverlapFailures,-- -- Inert CDictCans- DictMap, emptyDictMap, lookupInertDict, findDictsByClass, addDict,- addDictsByClass, delDict, foldDicts, filterDicts, findDict,-- -- Inert CTyEqCans- EqualCtList, findTyEqs, foldTyEqs, isInInertEqs,- lookupInertTyVar,-- -- Inert solved dictionaries- addSolvedDict, lookupSolvedDict,-- -- Irreds- foldIrreds,-- -- The flattening cache- lookupFlatCache, extendFlatCache, newFlattenSkolem, -- Flatten skolems- dischargeFunEq, pprKicked,-- -- Inert CFunEqCans- updInertFunEqs, findFunEq,- findFunEqsByTyCon,-- instDFunType, -- Instantiation-- -- MetaTyVars- newFlexiTcSTy, instFlexi, instFlexiX,- cloneMetaTyVar, demoteUnfilledFmv,- tcInstSkolTyVarsX,-- TcLevel,- isFilledMetaTyVar_maybe, isFilledMetaTyVar,- zonkTyCoVarsAndFV, zonkTcType, zonkTcTypes, zonkTcTyVar, zonkCo,- zonkTyCoVarsAndFVList,- zonkSimples, zonkWC,- zonkTyCoVarKind,-- -- References- newTcRef, readTcRef, writeTcRef, updTcRef,-- -- Misc- getDefaultInfo, getDynFlags, getGlobalRdrEnvTcS,- matchFam, matchFamTcM,- checkWellStagedDFun,- pprEq -- Smaller utils, re-exported from TcM- -- TODO (DV): these are only really used in the- -- instance matcher in GHC.Tc.Solver. I am wondering- -- if the whole instance matcher simply belongs- -- here-) where--#include "GhclibHsVersions.h"--import GHC.Prelude--import GHC.Driver.Env--import qualified GHC.Tc.Utils.Instantiate as TcM-import GHC.Core.InstEnv-import GHC.Tc.Instance.Family as FamInst-import GHC.Core.FamInstEnv--import qualified GHC.Tc.Utils.Monad as TcM-import qualified GHC.Tc.Utils.TcMType as TcM-import qualified GHC.Tc.Instance.Class as TcM( matchGlobalInst, ClsInstResult(..) )-import qualified GHC.Tc.Utils.Env as TcM- ( checkWellStaged, tcGetDefaultTys, tcLookupClass, tcLookupId, topIdLvl )-import GHC.Tc.Instance.Class( InstanceWhat(..), safeOverlap, instanceReturnsDictCon )-import GHC.Tc.Utils.TcType-import GHC.Driver.Session-import GHC.Core.Type-import GHC.Core.Coercion-import GHC.Core.Unify--import GHC.Utils.Error-import GHC.Tc.Types.Evidence-import GHC.Core.Class-import GHC.Core.TyCon-import GHC.Tc.Errors ( solverDepthErrorTcS )--import GHC.Types.Name-import GHC.Types.TyThing-import GHC.Unit.Module ( HasModule, getModule )-import GHC.Types.Name.Reader ( GlobalRdrEnv, GlobalRdrElt )-import qualified GHC.Rename.Env as TcM-import GHC.Types.Var-import GHC.Types.Var.Env-import GHC.Types.Var.Set-import GHC.Utils.Outputable-import GHC.Utils.Panic-import GHC.Data.Bag as Bag-import GHC.Types.Unique.Supply-import GHC.Utils.Misc-import GHC.Tc.Types-import GHC.Tc.Types.Origin-import GHC.Tc.Types.Constraint-import GHC.Core.Predicate--import GHC.Types.Unique-import GHC.Types.Unique.FM-import GHC.Types.Unique.DFM-import GHC.Core.TyCon.Env-import GHC.Data.Maybe--import GHC.Core.Map-import Control.Monad-import GHC.Utils.Monad-import Data.IORef-import Data.List ( partition, mapAccumL )--#if defined(DEBUG)-import GHC.Data.Graph.Directed-import GHC.Types.Unique.Set-#endif--{--************************************************************************-* *-* Worklists *-* Canonical and non-canonical constraints that the simplifier has to *-* work on. Including their simplification depths. *-* *-* *-************************************************************************--Note [WorkList priorities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~-A WorkList contains canonical and non-canonical items (of all flavours).-Notice that each Ct now has a simplification depth. We may-consider using this depth for prioritization as well in the future.--As a simple form of priority queue, our worklist separates out--* equalities (wl_eqs); see Note [Prioritise equalities]-* type-function equalities (wl_funeqs)-* all the rest (wl_rest)--Note [Prioritise equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-It's very important to process equalities /first/:--* (Efficiency) The general reason to do so is that if we process a- class constraint first, we may end up putting it into the inert set- and then kicking it out later. That's extra work compared to just- doing the equality first.--* (Avoiding fundep iteration) As #14723 showed, it's possible to- get non-termination if we- - Emit the Derived fundep equalities for a class constraint,- generating some fresh unification variables.- - That leads to some unification- - Which kicks out the class constraint- - Which isn't solved (because there are still some more Derived- equalities in the work-list), but generates yet more fundeps- Solution: prioritise derived equalities over class constraints--* (Class equalities) We need to prioritise equalities even if they- are hidden inside a class constraint;- see Note [Prioritise class equalities]--* (Kick-out) We want to apply this priority scheme to kicked-out- constraints too (see the call to extendWorkListCt in kick_out_rewritable- E.g. a CIrredCan can be a hetero-kinded (t1 ~ t2), which may become- homo-kinded when kicked out, and hence we want to prioritise it.--* (Derived equalities) Originally we tried to postpone processing- Derived equalities, in the hope that we might never need to deal- with them at all; but in fact we must process Derived equalities- eagerly, partly for the (Efficiency) reason, and more importantly- for (Avoiding fundep iteration).--Note [Prioritise class equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We prioritise equalities in the solver (see selectWorkItem). But class-constraints like (a ~ b) and (a ~~ b) are actually equalities too;-see Note [The equality types story] in GHC.Builtin.Types.Prim.--Failing to prioritise these is inefficient (more kick-outs etc).-But, worse, it can prevent us spotting a "recursive knot" among-Wanted constraints. See comment:10 of #12734 for a worked-out-example.--So we arrange to put these particular class constraints in the wl_eqs.-- NB: since we do not currently apply the substitution to the- inert_solved_dicts, the knot-tying still seems a bit fragile.- But this makes it better.---}---- See Note [WorkList priorities]-data WorkList- = WL { wl_eqs :: [Ct] -- CTyEqCan, CDictCan, CIrredCan- -- Given, Wanted, and Derived- -- Contains both equality constraints and their- -- class-level variants (a~b) and (a~~b);- -- See Note [Prioritise equalities]- -- See Note [Prioritise class equalities]-- , wl_funeqs :: [Ct]-- , wl_rest :: [Ct]-- , wl_implics :: Bag Implication -- See Note [Residual implications]- }--appendWorkList :: WorkList -> WorkList -> WorkList-appendWorkList- (WL { wl_eqs = eqs1, wl_funeqs = funeqs1, wl_rest = rest1- , wl_implics = implics1 })- (WL { wl_eqs = eqs2, wl_funeqs = funeqs2, wl_rest = rest2- , wl_implics = implics2 })- = WL { wl_eqs = eqs1 ++ eqs2- , wl_funeqs = funeqs1 ++ funeqs2- , wl_rest = rest1 ++ rest2- , wl_implics = implics1 `unionBags` implics2 }--workListSize :: WorkList -> Int-workListSize (WL { wl_eqs = eqs, wl_funeqs = funeqs, wl_rest = rest })- = length eqs + length funeqs + length rest--workListWantedCount :: WorkList -> Int--- Count the things we need to solve--- excluding the insolubles (c.f. inert_count)-workListWantedCount (WL { wl_eqs = eqs, wl_rest = rest })- = count isWantedCt eqs + count is_wanted rest- where- is_wanted ct- | CIrredCan { cc_status = InsolubleCIS } <- ct- = False- | otherwise- = isWantedCt ct--extendWorkListEq :: Ct -> WorkList -> WorkList-extendWorkListEq ct wl = wl { wl_eqs = ct : wl_eqs wl }--extendWorkListFunEq :: Ct -> WorkList -> WorkList-extendWorkListFunEq ct wl = wl { wl_funeqs = ct : wl_funeqs wl }--extendWorkListNonEq :: Ct -> WorkList -> WorkList--- Extension by non equality-extendWorkListNonEq ct wl = wl { wl_rest = ct : wl_rest wl }--extendWorkListDeriveds :: [CtEvidence] -> WorkList -> WorkList-extendWorkListDeriveds evs wl- = extendWorkListCts (map mkNonCanonical evs) wl--extendWorkListImplic :: Implication -> WorkList -> WorkList-extendWorkListImplic implic wl = wl { wl_implics = implic `consBag` wl_implics wl }--extendWorkListCt :: Ct -> WorkList -> WorkList--- Agnostic-extendWorkListCt ct wl- = case classifyPredType (ctPred ct) of- EqPred NomEq ty1 _- | Just tc <- tcTyConAppTyCon_maybe ty1- , isTypeFamilyTyCon tc- -> extendWorkListFunEq ct wl-- EqPred {}- -> extendWorkListEq ct wl-- ClassPred cls _ -- See Note [Prioritise class equalities]- | isEqPredClass cls- -> extendWorkListEq ct wl-- _ -> extendWorkListNonEq ct wl--extendWorkListCts :: [Ct] -> WorkList -> WorkList--- Agnostic-extendWorkListCts cts wl = foldr extendWorkListCt wl cts--isEmptyWorkList :: WorkList -> Bool-isEmptyWorkList (WL { wl_eqs = eqs, wl_funeqs = funeqs- , wl_rest = rest, wl_implics = implics })- = null eqs && null rest && null funeqs && isEmptyBag implics--emptyWorkList :: WorkList-emptyWorkList = WL { wl_eqs = [], wl_rest = []- , wl_funeqs = [], wl_implics = emptyBag }--selectWorkItem :: WorkList -> Maybe (Ct, WorkList)--- See Note [Prioritise equalities]-selectWorkItem wl@(WL { wl_eqs = eqs, wl_funeqs = feqs- , wl_rest = rest })- | ct:cts <- eqs = Just (ct, wl { wl_eqs = cts })- | ct:fes <- feqs = Just (ct, wl { wl_funeqs = fes })- | ct:cts <- rest = Just (ct, wl { wl_rest = cts })- | otherwise = Nothing--getWorkList :: TcS WorkList-getWorkList = do { wl_var <- getTcSWorkListRef- ; wrapTcS (TcM.readTcRef wl_var) }--selectNextWorkItem :: TcS (Maybe Ct)--- Pick which work item to do next--- See Note [Prioritise equalities]-selectNextWorkItem- = do { wl_var <- getTcSWorkListRef- ; wl <- readTcRef wl_var- ; case selectWorkItem wl of {- Nothing -> return Nothing ;- Just (ct, new_wl) ->- do { -- checkReductionDepth (ctLoc ct) (ctPred ct)- -- This is done by GHC.Tc.Solver.Interact.chooseInstance- ; writeTcRef wl_var new_wl- ; return (Just ct) } } }---- Pretty printing-instance Outputable WorkList where- ppr (WL { wl_eqs = eqs, wl_funeqs = feqs- , wl_rest = rest, wl_implics = implics })- = text "WL" <+> (braces $- vcat [ ppUnless (null eqs) $- text "Eqs =" <+> vcat (map ppr eqs)- , ppUnless (null feqs) $- text "Funeqs =" <+> vcat (map ppr feqs)- , ppUnless (null rest) $- text "Non-eqs =" <+> vcat (map ppr rest)- , ppUnless (isEmptyBag implics) $- ifPprDebug (text "Implics =" <+> vcat (map ppr (bagToList implics)))- (text "(Implics omitted)")- ])---{- *********************************************************************-* *- InertSet: the inert set-* *-* *-********************************************************************* -}--data InertSet- = IS { inert_cans :: InertCans- -- Canonical Given, Wanted, Derived- -- Sometimes called "the inert set"-- , inert_fsks :: [(TcTyVar, TcType)]- -- A list of (fsk, ty) pairs; we add one element when we flatten- -- a function application in a Given constraint, creating- -- a new fsk in newFlattenSkolem. When leaving a nested scope,- -- unflattenGivens unifies fsk := ty- --- -- We could also get this info from inert_funeqs, filtered by- -- level, but it seems simpler and more direct to capture the- -- fsk as we generate them.-- , inert_flat_cache :: ExactFunEqMap (TcCoercion, TcType, CtFlavour)- -- See Note [Type family equations]- -- If F tys :-> (co, rhs, flav),- -- then co :: F tys ~ rhs- -- flav is [G] or [WD]- --- -- Just a hash-cons cache for use when flattening only- -- These include entirely un-processed goals, so don't use- -- them to solve a top-level goal, else you may end up solving- -- (w:F ty ~ a) by setting w:=w! We just use the flat-cache- -- when allocating a new flatten-skolem.- -- Not necessarily inert wrt top-level equations (or inert_cans)-- -- NB: An ExactFunEqMap -- this doesn't match via loose types!-- , inert_solved_dicts :: DictMap CtEvidence- -- All Wanteds, of form ev :: C t1 .. tn- -- See Note [Solved dictionaries]- -- and Note [Do not add superclasses of solved dictionaries]- }--instance Outputable InertSet where- ppr (IS { inert_cans = ics- , inert_fsks = ifsks- , inert_solved_dicts = solved_dicts })- = vcat [ ppr ics- , text "Inert fsks =" <+> ppr ifsks- , ppUnless (null dicts) $- text "Solved dicts =" <+> vcat (map ppr dicts) ]- where- dicts = bagToList (dictsToBag solved_dicts)--emptyInertCans :: InertCans-emptyInertCans- = IC { inert_count = 0- , inert_eqs = emptyDVarEnv- , inert_dicts = emptyDicts- , inert_safehask = emptyDicts- , inert_funeqs = emptyFunEqs- , inert_insts = []- , inert_irreds = emptyCts }--emptyInert :: InertSet-emptyInert- = IS { inert_cans = emptyInertCans- , inert_fsks = []- , inert_flat_cache = emptyExactFunEqs- , inert_solved_dicts = emptyDictMap }---{- Note [Solved dictionaries]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When we apply a top-level instance declaration, we add the "solved"-dictionary to the inert_solved_dicts. In general, we use it to avoid-creating a new EvVar when we have a new goal that we have solved in-the past.--But in particular, we can use it to create *recursive* dictionaries.-The simplest, degenerate case is- instance C [a] => C [a] where ...-If we have- [W] d1 :: C [x]-then we can apply the instance to get- d1 = $dfCList d- [W] d2 :: C [x]-Now 'd1' goes in inert_solved_dicts, and we can solve d2 directly from d1.- d1 = $dfCList d- d2 = d1--See Note [Example of recursive dictionaries]--VERY IMPORTANT INVARIANT:-- (Solved Dictionary Invariant)- Every member of the inert_solved_dicts is the result- of applying an instance declaration that "takes a step"-- An instance "takes a step" if it has the form- dfunDList d1 d2 = MkD (...) (...) (...)- That is, the dfun is lazy in its arguments, and guarantees to- immediately return a dictionary constructor. NB: all dictionary- data constructors are lazy in their arguments.-- This property is crucial to ensure that all dictionaries are- non-bottom, which in turn ensures that the whole "recursive- dictionary" idea works at all, even if we get something like- rec { d = dfunDList d dx }- See Note [Recursive superclasses] in GHC.Tc.TyCl.Instance.-- Reason:- - All instances, except two exceptions listed below, "take a step"- in the above sense-- - Exception 1: local quantified constraints have no such guarantee;- indeed, adding a "solved dictionary" when appling a quantified- constraint led to the ability to define unsafeCoerce- in #17267.-- - Exception 2: the magic built-in instance for (~) has no- such guarantee. It behaves as if we had- class (a ~# b) => (a ~ b) where {}- instance (a ~# b) => (a ~ b) where {}- The "dfun" for the instance is strict in the coercion.- Anyway there's no point in recording a "solved dict" for- (t1 ~ t2); it's not going to allow a recursive dictionary- to be constructed. Ditto (~~) and Coercible.--THEREFORE we only add a "solved dictionary"- - when applying an instance declaration- - subject to Exceptions 1 and 2 above--In implementation terms- - GHC.Tc.Solver.Monad.addSolvedDict adds a new solved dictionary,- conditional on the kind of instance-- - It is only called when applying an instance decl,- in GHC.Tc.Solver.Interact.doTopReactDict-- - ClsInst.InstanceWhat says what kind of instance was- used to solve the constraint. In particular- * LocalInstance identifies quantified constraints- * BuiltinEqInstance identifies the strange built-in- instances for equality.-- - ClsInst.instanceReturnsDictCon says which kind of- instance guarantees to return a dictionary constructor--Other notes about solved dictionaries--* See also Note [Do not add superclasses of solved dictionaries]--* The inert_solved_dicts field is not rewritten by equalities,- so it may get out of date.--* The inert_solved_dicts are all Wanteds, never givens--* We only cache dictionaries from top-level instances, not from- local quantified constraints. Reason: if we cached the latter- we'd need to purge the cache when bringing new quantified- constraints into scope, because quantified constraints "shadow"- top-level instances.--Note [Do not add superclasses of solved dictionaries]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Every member of inert_solved_dicts is the result of applying a-dictionary function, NOT of applying superclass selection to anything.-Consider-- class Ord a => C a where- instance Ord [a] => C [a] where ...--Suppose we are trying to solve- [G] d1 : Ord a- [W] d2 : C [a]--Then we'll use the instance decl to give-- [G] d1 : Ord a Solved: d2 : C [a] = $dfCList d3- [W] d3 : Ord [a]--We must not add d4 : Ord [a] to the 'solved' set (by taking the-superclass of d2), otherwise we'll use it to solve d3, without ever-using d1, which would be a catastrophe.--Solution: when extending the solved dictionaries, do not add superclasses.-That's why each element of the inert_solved_dicts is the result of applying-a dictionary function.--Note [Example of recursive dictionaries]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~---- Example 1-- data D r = ZeroD | SuccD (r (D r));-- instance (Eq (r (D r))) => Eq (D r) where- ZeroD == ZeroD = True- (SuccD a) == (SuccD b) = a == b- _ == _ = False;-- equalDC :: D [] -> D [] -> Bool;- equalDC = (==);--We need to prove (Eq (D [])). Here's how we go:-- [W] d1 : Eq (D [])-By instance decl of Eq (D r):- [W] d2 : Eq [D []] where d1 = dfEqD d2-By instance decl of Eq [a]:- [W] d3 : Eq (D []) where d2 = dfEqList d3- d1 = dfEqD d2-Now this wanted can interact with our "solved" d1 to get:- d3 = d1---- Example 2:-This code arises in the context of "Scrap Your Boilerplate with Class"-- class Sat a- class Data ctx a- instance Sat (ctx Char) => Data ctx Char -- dfunData1- instance (Sat (ctx [a]), Data ctx a) => Data ctx [a] -- dfunData2-- class Data Maybe a => Foo a-- instance Foo t => Sat (Maybe t) -- dfunSat-- instance Data Maybe a => Foo a -- dfunFoo1- instance Foo a => Foo [a] -- dfunFoo2- instance Foo [Char] -- dfunFoo3--Consider generating the superclasses of the instance declaration- instance Foo a => Foo [a]--So our problem is this- [G] d0 : Foo t- [W] d1 : Data Maybe [t] -- Desired superclass--We may add the given in the inert set, along with its superclasses- Inert:- [G] d0 : Foo t- [G] d01 : Data Maybe t -- Superclass of d0- WorkList- [W] d1 : Data Maybe [t]--Solve d1 using instance dfunData2; d1 := dfunData2 d2 d3- Inert:- [G] d0 : Foo t- [G] d01 : Data Maybe t -- Superclass of d0- Solved:- d1 : Data Maybe [t]- WorkList:- [W] d2 : Sat (Maybe [t])- [W] d3 : Data Maybe t--Now, we may simplify d2 using dfunSat; d2 := dfunSat d4- Inert:- [G] d0 : Foo t- [G] d01 : Data Maybe t -- Superclass of d0- Solved:- d1 : Data Maybe [t]- d2 : Sat (Maybe [t])- WorkList:- [W] d3 : Data Maybe t- [W] d4 : Foo [t]--Now, we can just solve d3 from d01; d3 := d01- Inert- [G] d0 : Foo t- [G] d01 : Data Maybe t -- Superclass of d0- Solved:- d1 : Data Maybe [t]- d2 : Sat (Maybe [t])- WorkList- [W] d4 : Foo [t]--Now, solve d4 using dfunFoo2; d4 := dfunFoo2 d5- Inert- [G] d0 : Foo t- [G] d01 : Data Maybe t -- Superclass of d0- Solved:- d1 : Data Maybe [t]- d2 : Sat (Maybe [t])- d4 : Foo [t]- WorkList:- [W] d5 : Foo t--Now, d5 can be solved! d5 := d0--Result- d1 := dfunData2 d2 d3- d2 := dfunSat d4- d3 := d01- d4 := dfunFoo2 d5- d5 := d0--}--{- *********************************************************************-* *- InertCans: the canonical inerts-* *-* *-********************************************************************* -}--data InertCans -- See Note [Detailed InertCans Invariants] for more- = IC { inert_eqs :: InertEqs- -- See Note [inert_eqs: the inert equalities]- -- All CTyEqCans; index is the LHS tyvar- -- Domain = skolems and untouchables; a touchable would be unified-- , inert_funeqs :: FunEqMap Ct- -- All CFunEqCans; index is the whole family head type.- -- All Nominal (that's an invariant of all CFunEqCans)- -- LHS is fully rewritten (modulo eqCanRewrite constraints)- -- wrt inert_eqs- -- Can include all flavours, [G], [W], [WD], [D]- -- See Note [Type family equations]-- , inert_dicts :: DictMap Ct- -- Dictionaries only- -- All fully rewritten (modulo flavour constraints)- -- wrt inert_eqs-- , inert_insts :: [QCInst]-- , inert_safehask :: DictMap Ct- -- Failed dictionary resolution due to Safe Haskell overlapping- -- instances restriction. We keep this separate from inert_dicts- -- as it doesn't cause compilation failure, just safe inference- -- failure.- --- -- ^ See Note [Safe Haskell Overlapping Instances Implementation]- -- in "GHC.Tc.Solver"-- , inert_irreds :: Cts- -- Irreducible predicates that cannot be made canonical,- -- and which don't interact with others (e.g. (c a))- -- and insoluble predicates (e.g. Int ~ Bool, or a ~ [a])-- , inert_count :: Int- -- Number of Wanted goals in- -- inert_eqs, inert_dicts, inert_safehask, inert_irreds- -- Does not include insolubles- -- When non-zero, keep trying to solve- }--type InertEqs = DTyVarEnv EqualCtList-type EqualCtList = [Ct] -- See Note [EqualCtList invariants]--{- Note [Detailed InertCans Invariants]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The InertCans represents a collection of constraints with the following properties:-- * All canonical-- * No two dictionaries with the same head- * No two CIrreds with the same type-- * Family equations inert wrt top-level family axioms-- * Dictionaries have no matching top-level instance-- * Given family or dictionary constraints don't mention touchable- unification variables-- * Non-CTyEqCan constraints are fully rewritten with respect- to the CTyEqCan equalities (modulo canRewrite of course;- eg a wanted cannot rewrite a given)-- * CTyEqCan equalities: see Note [inert_eqs: the inert equalities]- Also see documentation in Constraint.Ct for a list of invariants--Note [EqualCtList invariants]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~- * All are equalities- * All these equalities have the same LHS- * The list is never empty- * No element of the list can rewrite any other- * Derived before Wanted--From the fourth invariant it follows that the list is- - A single [G], or- - Zero or one [D] or [WD], followed by any number of [W]--The Wanteds can't rewrite anything which is why we put them last--Note [Type family equations]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Type-family equations, CFunEqCans, of form (ev : F tys ~ ty),-live in three places-- * The work-list, of course-- * The inert_funeqs are un-solved but fully processed, and in- the InertCans. They can be [G], [W], [WD], or [D].-- * The inert_flat_cache. This is used when flattening, to get maximal- sharing. Everything in the inert_flat_cache is [G] or [WD]-- It contains lots of things that are still in the work-list.- E.g Suppose we have (w1: F (G a) ~ Int), and (w2: H (G a) ~ Int) in the- work list. Then we flatten w1, dumping (w3: G a ~ f1) in the work- list. Now if we flatten w2 before we get to w3, we still want to- share that (G a).- Because it contains work-list things, DO NOT use the flat cache to solve- a top-level goal. Eg in the above example we don't want to solve w3- using w3 itself!--The CFunEqCan Ownership Invariant:-- * Each [G/W/WD] CFunEqCan has a distinct fsk or fmv- It "owns" that fsk/fmv, in the sense that:- - reducing a [W/WD] CFunEqCan fills in the fmv- - unflattening a [W/WD] CFunEqCan fills in the fmv- (in both cases unless an occurs-check would result)-- * In contrast a [D] CFunEqCan does not "own" its fmv:- - reducing a [D] CFunEqCan does not fill in the fmv;- it just generates an equality- - unflattening ignores [D] CFunEqCans altogether---Note [inert_eqs: the inert equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Definition [Can-rewrite relation]-A "can-rewrite" relation between flavours, written f1 >= f2, is a-binary relation with the following properties-- (R1) >= is transitive- (R2) If f1 >= f, and f2 >= f,- then either f1 >= f2 or f2 >= f1--Lemma. If f1 >= f then f1 >= f1-Proof. By property (R2), with f1=f2--Definition [Generalised substitution]-A "generalised substitution" S is a set of triples (a -f-> t), where- a is a type variable- t is a type- f is a flavour-such that- (WF1) if (a -f1-> t1) in S- (a -f2-> t2) in S- then neither (f1 >= f2) nor (f2 >= f1) hold- (WF2) if (a -f-> t) is in S, then t /= a--Definition [Applying a generalised substitution]-If S is a generalised substitution- S(f,a) = t, if (a -fs-> t) in S, and fs >= f- = a, otherwise-Application extends naturally to types S(f,t), modulo roles.-See Note [Flavours with roles].--Theorem: S(f,a) is well defined as a function.-Proof: Suppose (a -f1-> t1) and (a -f2-> t2) are both in S,- and f1 >= f and f2 >= f- Then by (R2) f1 >= f2 or f2 >= f1, which contradicts (WF1)--Notation: repeated application.- S^0(f,t) = t- S^(n+1)(f,t) = S(f, S^n(t))--Definition: inert generalised substitution-A generalised substitution S is "inert" iff-- (IG1) there is an n such that- for every f,t, S^n(f,t) = S^(n+1)(f,t)--By (IG1) we define S*(f,t) to be the result of exahaustively-applying S(f,_) to t.-------------------------------------------------------------------Our main invariant:- the inert CTyEqCans should be an inert generalised substitution-------------------------------------------------------------------Note that inertness is not the same as idempotence. To apply S to a-type, you may have to apply it recursive. But inertness does-guarantee that this recursive use will terminate.--Note [Extending the inert equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Main Theorem [Stability under extension]- Suppose we have a "work item"- a -fw-> t- and an inert generalised substitution S,- THEN the extended substitution T = S+(a -fw-> t)- is an inert generalised substitution- PROVIDED- (T1) S(fw,a) = a -- LHS of work-item is a fixpoint of S(fw,_)- (T2) S(fw,t) = t -- RHS of work-item is a fixpoint of S(fw,_)- (T3) a not in t -- No occurs check in the work item-- AND, for every (b -fs-> s) in S:- (K0) not (fw >= fs)- Reason: suppose we kick out (a -fs-> s),- and add (a -fw-> t) to the inert set.- The latter can't rewrite the former,- so the kick-out achieved nothing-- OR { (K1) not (a = b)- Reason: if fw >= fs, WF1 says we can't have both- a -fw-> t and a -fs-> s-- AND (K2): guarantees inertness of the new substitution- { (K2a) not (fs >= fs)- OR (K2b) fs >= fw- OR (K2d) a not in s }-- AND (K3) See Note [K3: completeness of solving]- { (K3a) If the role of fs is nominal: s /= a- (K3b) If the role of fs is representational:- s is not of form (a t1 .. tn) } }---Conditions (T1-T3) are established by the canonicaliser-Conditions (K1-K3) are established by GHC.Tc.Solver.Monad.kickOutRewritable--The idea is that-* (T1-2) are guaranteed by exhaustively rewriting the work-item- with S(fw,_).--* T3 is guaranteed by a simple occurs-check on the work item.- This is done during canonicalisation, in canEqTyVar; invariant- (TyEq:OC) of CTyEqCan.--* (K1-3) are the "kick-out" criteria. (As stated, they are really the- "keep" criteria.) If the current inert S contains a triple that does- not satisfy (K1-3), then we remove it from S by "kicking it out",- and re-processing it.--* Note that kicking out is a Bad Thing, because it means we have to- re-process a constraint. The less we kick out, the better.- TODO: Make sure that kicking out really *is* a Bad Thing. We've assumed- this but haven't done the empirical study to check.--* Assume we have G>=G, G>=W and that's all. Then, when performing- a unification we add a new given a -G-> ty. But doing so does NOT require- us to kick out an inert wanted that mentions a, because of (K2a). This- is a common case, hence good not to kick out.--* Lemma (L2): if not (fw >= fw), then K0 holds and we kick out nothing- Proof: using Definition [Can-rewrite relation], fw can't rewrite anything- and so K0 holds. Intuitively, since fw can't rewrite anything,- adding it cannot cause any loops- This is a common case, because Wanteds cannot rewrite Wanteds.- It's used to avoid even looking for constraint to kick out.--* Lemma (L1): The conditions of the Main Theorem imply that there is no- (a -fs-> t) in S, s.t. (fs >= fw).- Proof. Suppose the contrary (fs >= fw). Then because of (T1),- S(fw,a)=a. But since fs>=fw, S(fw,a) = s, hence s=a. But now we- have (a -fs-> a) in S, which contradicts (WF2).--* The extended substitution satisfies (WF1) and (WF2)- - (K1) plus (L1) guarantee that the extended substitution satisfies (WF1).- - (T3) guarantees (WF2).--* (K2) is about inertness. Intuitively, any infinite chain T^0(f,t),- T^1(f,t), T^2(f,T).... must pass through the new work item infinitely- often, since the substitution without the work item is inert; and must- pass through at least one of the triples in S infinitely often.-- - (K2a): if not(fs>=fs) then there is no f that fs can rewrite (fs>=f),- and hence this triple never plays a role in application S(f,a).- It is always safe to extend S with such a triple.-- (NB: we could strengten K1) in this way too, but see K3.-- - (K2b): If this holds then, by (T2), b is not in t. So applying the- work item does not generate any new opportunities for applying S-- - (K2c): If this holds, we can't pass through this triple infinitely- often, because if we did then fs>=f, fw>=f, hence by (R2)- * either fw>=fs, contradicting K2c- * or fs>=fw; so by the argument in K2b we can't have a loop-- - (K2d): if a not in s, we hae no further opportunity to apply the- work item, similar to (K2b)-- NB: Dimitrios has a PDF that does this in more detail--Key lemma to make it watertight.- Under the conditions of the Main Theorem,- forall f st fw >= f, a is not in S^k(f,t), for any k--Also, consider roles more carefully. See Note [Flavours with roles]--Note [K3: completeness of solving]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-(K3) is not necessary for the extended substitution-to be inert. In fact K1 could be made stronger by saying- ... then (not (fw >= fs) or not (fs >= fs))-But it's not enough for S to be inert; we also want completeness.-That is, we want to be able to solve all soluble wanted equalities.-Suppose we have-- work-item b -G-> a- inert-item a -W-> b--Assuming (G >= W) but not (W >= W), this fulfills all the conditions,-so we could extend the inerts, thus:-- inert-items b -G-> a- a -W-> b--But if we kicked-out the inert item, we'd get-- work-item a -W-> b- inert-item b -G-> a--Then rewrite the work-item gives us (a -W-> a), which is soluble via Refl.-So we add one more clause to the kick-out criteria--Another way to understand (K3) is that we treat an inert item- a -f-> b-in the same way as- b -f-> a-So if we kick out one, we should kick out the other. The orientation-is somewhat accidental.--When considering roles, we also need the second clause (K3b). Consider-- work-item c -G/N-> a- inert-item a -W/R-> b c--The work-item doesn't get rewritten by the inert, because (>=) doesn't hold.-But we don't kick out the inert item because not (W/R >= W/R). So we just-add the work item. But then, consider if we hit the following:-- work-item b -G/N-> Id- inert-items a -W/R-> b c- c -G/N-> a-where- newtype Id x = Id x--For similar reasons, if we only had (K3a), we wouldn't kick the-representational inert out. And then, we'd miss solving the inert, which-now reduced to reflexivity.--The solution here is to kick out representational inerts whenever the-tyvar of a work item is "exposed", where exposed means being at the-head of the top-level application chain (a t1 .. tn). See-TcType.isTyVarHead. This is encoded in (K3b).--Beware: if we make this test succeed too often, we kick out too much,-and the solver might loop. Consider (#14363)- work item: [G] a ~R f b- inert item: [G] b ~R f a-In GHC 8.2 the completeness tests more aggressive, and kicked out-the inert item; but no rewriting happened and there was an infinite-loop. All we need is to have the tyvar at the head.--Note [Flavours with roles]-~~~~~~~~~~~~~~~~~~~~~~~~~~-The system described in Note [inert_eqs: the inert equalities]-discusses an abstract-set of flavours. In GHC, flavours have two components: the flavour proper,-taken from {Wanted, Derived, Given} and the equality relation (often called-role), taken from {NomEq, ReprEq}.-When substituting w.r.t. the inert set,-as described in Note [inert_eqs: the inert equalities],-we must be careful to respect all components of a flavour.-For example, if we have-- inert set: a -G/R-> Int- b -G/R-> Bool-- type role T nominal representational--and we wish to compute S(W/R, T a b), the correct answer is T a Bool, NOT-T Int Bool. The reason is that T's first parameter has a nominal role, and-thus rewriting a to Int in T a b is wrong. Indeed, this non-congruence of-substitution means that the proof in Note [The inert equalities] may need-to be revisited, but we don't think that the end conclusion is wrong.--}--instance Outputable InertCans where- ppr (IC { inert_eqs = eqs- , inert_funeqs = funeqs, inert_dicts = dicts- , inert_safehask = safehask, inert_irreds = irreds- , inert_insts = insts- , inert_count = count })- = braces $ vcat- [ ppUnless (isEmptyDVarEnv eqs) $- text "Equalities:"- <+> pprCts (foldDVarEnv (\eqs rest -> listToBag eqs `andCts` rest) emptyCts eqs)- , ppUnless (isEmptyTcAppMap funeqs) $- text "Type-function equalities =" <+> pprCts (funEqsToBag funeqs)- , ppUnless (isEmptyTcAppMap dicts) $- text "Dictionaries =" <+> pprCts (dictsToBag dicts)- , ppUnless (isEmptyTcAppMap safehask) $- text "Safe Haskell unsafe overlap =" <+> pprCts (dictsToBag safehask)- , ppUnless (isEmptyCts irreds) $- text "Irreds =" <+> pprCts irreds- , ppUnless (null insts) $- text "Given instances =" <+> vcat (map ppr insts)- , text "Unsolved goals =" <+> int count- ]--{- *********************************************************************-* *- Shadow constraints and improvement-* *-************************************************************************--Note [The improvement story and derived shadows]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Because Wanteds cannot rewrite Wanteds (see Note [Wanteds do not-rewrite Wanteds] in GHC.Tc.Types.Constraint), we may miss some opportunities for-solving. Here's a classic example (indexed-types/should_fail/T4093a)-- Ambiguity check for f: (Foo e ~ Maybe e) => Foo e-- We get [G] Foo e ~ Maybe e- [W] Foo e ~ Foo ee -- ee is a unification variable- [W] Foo ee ~ Maybe ee-- Flatten: [G] Foo e ~ fsk- [G] fsk ~ Maybe e -- (A)-- [W] Foo ee ~ fmv- [W] fmv ~ fsk -- (B) From Foo e ~ Foo ee- [W] fmv ~ Maybe ee-- --> rewrite (B) with (A)- [W] Foo ee ~ fmv- [W] fmv ~ Maybe e- [W] fmv ~ Maybe ee-- But now we appear to be stuck, since we don't rewrite Wanteds with- Wanteds. This is silly because we can see that ee := e is the- only solution.--The basic plan is- * generate Derived constraints that shadow Wanted constraints- * allow Derived to rewrite Derived- * in order to cause some unifications to take place- * that in turn solve the original Wanteds--The ONLY reason for all these Derived equalities is to tell us how to-unify a variable: that is, what Mark Jones calls "improvement".--The same idea is sometimes also called "saturation"; find all the-equalities that must hold in any solution.--Or, equivalently, you can think of the derived shadows as implementing-the "model": a non-idempotent but no-occurs-check substitution,-reflecting *all* *Nominal* equalities (a ~N ty) that are not-immediately soluble by unification.--More specifically, here's how it works (Oct 16):--* Wanted constraints are born as [WD]; this behaves like a- [W] and a [D] paired together.--* When we are about to add a [WD] to the inert set, if it can- be rewritten by a [D] a ~ ty, then we split it into [W] and [D],- putting the latter into the work list (see maybeEmitShadow).--In the example above, we get to the point where we are stuck:- [WD] Foo ee ~ fmv- [WD] fmv ~ Maybe e- [WD] fmv ~ Maybe ee--But now when [WD] fmv ~ Maybe ee is about to be added, we'll-split it into [W] and [D], since the inert [WD] fmv ~ Maybe e-can rewrite it. Then:- work item: [D] fmv ~ Maybe ee- inert: [W] fmv ~ Maybe ee- [WD] fmv ~ Maybe e -- (C)- [WD] Foo ee ~ fmv--See Note [Splitting WD constraints]. Now the work item is rewritten-by (C) and we soon get ee := e.--Additional notes:-- * The derived shadow equalities live in inert_eqs, along with- the Givens and Wanteds; see Note [EqualCtList invariants].-- * We make Derived shadows only for Wanteds, not Givens. So we- have only [G], not [GD] and [G] plus splitting. See- Note [Add derived shadows only for Wanteds]-- * We also get Derived equalities from functional dependencies- and type-function injectivity; see calls to unifyDerived.-- * This splitting business applies to CFunEqCans too; and then- we do apply type-function reductions to the [D] CFunEqCan.- See Note [Reduction for Derived CFunEqCans]-- * It's worth having [WD] rather than just [W] and [D] because- * efficiency: silly to process the same thing twice- * inert_funeqs, inert_dicts is a finite map keyed by- the type; it's inconvenient for it to map to TWO constraints--Note [Splitting WD constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We are about to add a [WD] constraint to the inert set; and we-know that the inert set has fully rewritten it. Should we split-it into [W] and [D], and put the [D] in the work list for further-work?--* CDictCan (C tys) or CFunEqCan (F tys ~ fsk):- Yes if the inert set could rewrite tys to make the class constraint,- or type family, fire. That is, yes if the inert_eqs intersects- with the free vars of tys. For this test we use- (anyRewritableTyVar True) which ignores casts and coercions in tys,- because rewriting the casts or coercions won't make the thing fire- more often.--* CTyEqCan (a ~ ty): Yes if the inert set could rewrite 'a' or 'ty'.- We need to check both 'a' and 'ty' against the inert set:- - Inert set contains [D] a ~ ty2- Then we want to put [D] a ~ ty in the worklist, so we'll- get [D] ty ~ ty2 with consequent good things-- - Inert set contains [D] b ~ a, where b is in ty.- We can't just add [WD] a ~ ty[b] to the inert set, because- that breaks the inert-set invariants. If we tried to- canonicalise another [D] constraint mentioning 'a', we'd- get an infinite loop-- Moreover we must use (anyRewritableTyVar False) for the RHS,- because even tyvars in the casts and coercions could give- an infinite loop if we don't expose it--* CIrredCan: Yes if the inert set can rewrite the constraint.- We used to think splitting irreds was unnecessary, but- see Note [Splitting Irred WD constraints]--* Others: nothing is gained by splitting.--Note [Splitting Irred WD constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Splitting Irred constraints can make a difference. Here is the-scenario:-- a[sk] :: F v -- F is a type family- beta :: alpha-- work item: [WD] a ~ beta--This is heterogeneous, so we try flattening the kinds.-- co :: F v ~ fmv- [WD] (a |> co) ~ beta--This is still hetero, so we emit a kind equality and make the work item an-inert Irred.-- work item: [D] fmv ~ alpha- inert: [WD] (a |> co) ~ beta (CIrredCan)--Can't make progress on the work item. Add to inert set. This kicks out the-old inert, because a [D] can rewrite a [WD].-- work item: [WD] (a |> co) ~ beta- inert: [D] fmv ~ alpha (CTyEqCan)--Can't make progress on this work item either (although GHC tries by-decomposing the cast and reflattening... but that doesn't make a difference),-which is still hetero. Emit a new kind equality and add to inert set. But,-critically, we split the Irred.-- work list:- [D] fmv ~ alpha (CTyEqCan)- [D] (a |> co) ~ beta (CIrred) -- this one was split off- inert:- [W] (a |> co) ~ beta- [D] fmv ~ alpha--We quickly solve the first work item, as it's the same as an inert.-- work item: [D] (a |> co) ~ beta- inert:- [W] (a |> co) ~ beta- [D] fmv ~ alpha--We decompose the cast, yielding-- [D] a ~ beta--We then flatten the kinds. The lhs kind is F v, which flattens to fmv which-then rewrites to alpha.-- co' :: F v ~ alpha- [D] (a |> co') ~ beta--Now this equality is homo-kinded. So we swizzle it around to-- [D] beta ~ (a |> co')--and set beta := a |> co', and go home happy.--If we don't split the Irreds, we loop. This is all dangerously subtle.--This is triggered by test case typecheck/should_compile/SplitWD.--Note [Examples of how Derived shadows helps completeness]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Ticket #10009, a very nasty example:-- f :: (UnF (F b) ~ b) => F b -> ()-- g :: forall a. (UnF (F a) ~ a) => a -> ()- g _ = f (undefined :: F a)-- For g we get [G] UnF (F a) ~ a- [WD] UnF (F beta) ~ beta- [WD] F a ~ F beta- Flatten:- [G] g1: F a ~ fsk1 fsk1 := F a- [G] g2: UnF fsk1 ~ fsk2 fsk2 := UnF fsk1- [G] g3: fsk2 ~ a-- [WD] w1: F beta ~ fmv1- [WD] w2: UnF fmv1 ~ fmv2- [WD] w3: fmv2 ~ beta- [WD] w4: fmv1 ~ fsk1 -- From F a ~ F beta using flat-cache- -- and re-orient to put meta-var on left--Rewrite w2 with w4: [D] d1: UnF fsk1 ~ fmv2-React that with g2: [D] d2: fmv2 ~ fsk2-React that with w3: [D] beta ~ fsk2- and g3: [D] beta ~ a -- Hooray beta := a-And that is enough to solve everything--Note [Add derived shadows only for Wanteds]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We only add shadows for Wanted constraints. That is, we have-[WD] but not [GD]; and maybeEmitShaodw looks only at [WD]-constraints.--It does just possibly make sense ot add a derived shadow for a-Given. If we created a Derived shadow of a Given, it could be-rewritten by other Deriveds, and that could, conceivably, lead to a-useful unification.--But (a) I have been unable to come up with an example of this- happening- (b) see #12660 for how adding the derived shadows- of a Given led to an infinite loop.- (c) It's unlikely that rewriting derived Givens will lead- to a unification because Givens don't mention touchable- unification variables--For (b) there may be other ways to solve the loop, but simply-reraining from adding derived shadows of Givens is particularly-simple. And it's more efficient too!--Still, here's one possible reason for adding derived shadows-for Givens. Consider- work-item [G] a ~ [b], inerts has [D] b ~ a.-If we added the derived shadow (into the work list)- [D] a ~ [b]-When we process it, we'll rewrite to a ~ [a] and get an-occurs check. Without it we'll miss the occurs check (reporting-inaccessible code); but that's probably OK.--Note [Keep CDictCan shadows as CDictCan]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we have- class C a => D a b-and [G] D a b, [G] C a in the inert set. Now we insert-[D] b ~ c. We want to kick out a derived shadow for [D] D a b,-so we can rewrite it with the new constraint, and perhaps get-instance reduction or other consequences.--BUT we do not want to kick out a *non-canonical* (D a b). If we-did, we would do this:- - rewrite it to [D] D a c, with pend_sc = True- - use expandSuperClasses to add C a- - go round again, which solves C a from the givens-This loop goes on for ever and triggers the simpl_loop limit.--Solution: kick out the CDictCan which will have pend_sc = False,-because we've already added its superclasses. So we won't re-add-them. If we forget the pend_sc flag, our cunning scheme for avoiding-generating superclasses repeatedly will fail.--See #11379 for a case of this.--Note [Do not do improvement for WOnly]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We do improvement between two constraints (e.g. for injectivity-or functional dependencies) only if both are "improvable". And-we improve a constraint wrt the top-level instances only if-it is improvable.--Improvable: [G] [WD] [D}-Not improvable: [W]--Reasons:--* It's less work: fewer pairs to compare--* Every [W] has a shadow [D] so nothing is lost--* Consider [WD] C Int b, where 'b' is a skolem, and- class C a b | a -> b- instance C Int Bool- We'll do a fundep on it and emit [D] b ~ Bool- That will kick out constraint [WD] C Int b- Then we'll split it to [W] C Int b (keep in inert)- and [D] C Int b (in work list)- When processing the latter we'll rewrite it to- [D] C Int Bool- At that point it would be /stupid/ to interact it- with the inert [W] C Int b in the inert set; after all,- it's the very constraint from which the [D] C Int Bool- was split! We can avoid this by not doing improvement- on [W] constraints. This came up in #12860.--}--maybeEmitShadow :: InertCans -> Ct -> TcS Ct--- See Note [The improvement story and derived shadows]-maybeEmitShadow ics ct- | let ev = ctEvidence ct- , CtWanted { ctev_pred = pred, ctev_loc = loc- , ctev_nosh = WDeriv } <- ev- , shouldSplitWD (inert_eqs ics) ct- = do { traceTcS "Emit derived shadow" (ppr ct)- ; let derived_ev = CtDerived { ctev_pred = pred- , ctev_loc = loc }- shadow_ct = ct { cc_ev = derived_ev }- -- Te shadow constraint keeps the canonical shape.- -- This just saves work, but is sometimes important;- -- see Note [Keep CDictCan shadows as CDictCan]- ; emitWork [shadow_ct]-- ; let ev' = ev { ctev_nosh = WOnly }- ct' = ct { cc_ev = ev' }- -- Record that it now has a shadow- -- This is /the/ place we set the flag to WOnly- ; return ct' }-- | otherwise- = return ct--shouldSplitWD :: InertEqs -> Ct -> Bool--- Precondition: 'ct' is [WD], and is inert--- True <=> we should split ct ito [W] and [D] because--- the inert_eqs can make progress on the [D]--- See Note [Splitting WD constraints]--shouldSplitWD inert_eqs (CFunEqCan { cc_tyargs = tys })- = should_split_match_args inert_eqs tys- -- We don't need to split if the tv is the RHS fsk--shouldSplitWD inert_eqs (CDictCan { cc_tyargs = tys })- = should_split_match_args inert_eqs tys- -- NB True: ignore coercions- -- See Note [Splitting WD constraints]--shouldSplitWD inert_eqs (CTyEqCan { cc_tyvar = tv, cc_rhs = ty- , cc_eq_rel = eq_rel })- = tv `elemDVarEnv` inert_eqs- || anyRewritableTyVar False eq_rel (canRewriteTv inert_eqs) ty- -- NB False: do not ignore casts and coercions- -- See Note [Splitting WD constraints]--shouldSplitWD inert_eqs (CIrredCan { cc_ev = ev })- = anyRewritableTyVar False (ctEvEqRel ev) (canRewriteTv inert_eqs) (ctEvPred ev)--shouldSplitWD _ _ = False -- No point in splitting otherwise--should_split_match_args :: InertEqs -> [TcType] -> Bool--- True if the inert_eqs can rewrite anything in the argument--- types, ignoring casts and coercions-should_split_match_args inert_eqs tys- = any (anyRewritableTyVar True NomEq (canRewriteTv inert_eqs)) tys- -- NB True: ignore casts coercions- -- See Note [Splitting WD constraints]--canRewriteTv :: InertEqs -> EqRel -> TyVar -> Bool-canRewriteTv inert_eqs eq_rel tv- | Just (ct : _) <- lookupDVarEnv inert_eqs tv- , CTyEqCan { cc_eq_rel = eq_rel1 } <- ct- = eq_rel1 `eqCanRewrite` eq_rel- | otherwise- = False--isImprovable :: CtEvidence -> Bool--- See Note [Do not do improvement for WOnly]-isImprovable (CtWanted { ctev_nosh = WOnly }) = False-isImprovable _ = True---{- *********************************************************************-* *- Inert equalities-* *-********************************************************************* -}--addTyEq :: InertEqs -> TcTyVar -> Ct -> InertEqs-addTyEq old_eqs tv ct- = extendDVarEnv_C add_eq old_eqs tv [ct]- where- add_eq old_eqs _- | isWantedCt ct- , (eq1 : eqs) <- old_eqs- = eq1 : ct : eqs- | otherwise- = ct : old_eqs--foldTyEqs :: (Ct -> b -> b) -> InertEqs -> b -> b-foldTyEqs k eqs z- = foldDVarEnv (\cts z -> foldr k z cts) z eqs--findTyEqs :: InertCans -> TyVar -> EqualCtList-findTyEqs icans tv = lookupDVarEnv (inert_eqs icans) tv `orElse` []--delTyEq :: InertEqs -> TcTyVar -> TcType -> InertEqs-delTyEq m tv t = modifyDVarEnv (filter (not . isThisOne)) m tv- where isThisOne (CTyEqCan { cc_rhs = t1 }) = eqType t t1- isThisOne _ = False--lookupInertTyVar :: InertEqs -> TcTyVar -> Maybe TcType-lookupInertTyVar ieqs tv- = case lookupDVarEnv ieqs tv of- Just (CTyEqCan { cc_rhs = rhs, cc_eq_rel = NomEq } : _ ) -> Just rhs- _ -> Nothing--{- *********************************************************************-* *- Inert instances: inert_insts-* *-********************************************************************* -}--addInertForAll :: QCInst -> TcS ()--- Add a local Given instance, typically arising from a type signature-addInertForAll new_qci- = do { ics <- getInertCans- ; insts' <- add_qci (inert_insts ics)- ; setInertCans (ics { inert_insts = insts' }) }- where- add_qci :: [QCInst] -> TcS [QCInst]- -- See Note [Do not add duplicate quantified instances]- add_qci qcis- | any same_qci qcis- = do { traceTcS "skipping duplicate quantified instance" (ppr new_qci)- ; return qcis }-- | otherwise- = do { traceTcS "adding new inert quantified instance" (ppr new_qci)- ; return (new_qci : qcis) }-- same_qci old_qci = tcEqType (ctEvPred (qci_ev old_qci))- (ctEvPred (qci_ev new_qci))--{- Note [Do not add duplicate quantified instances]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider this (#15244):-- f :: (C g, D g) => ....- class S g => C g where ...- class S g => D g where ...- class (forall a. Eq a => Eq (g a)) => S g where ...--Then in f's RHS there are two identical quantified constraints-available, one via the superclasses of C and one via the superclasses-of D. The two are identical, and it seems wrong to reject the program-because of that. But without doing duplicate-elimination we will have-two matching QCInsts when we try to solve constraints arising from f's-RHS.--The simplest thing is simply to eliminate duplicates, which we do here.--}--{- *********************************************************************-* *- Adding an inert-* *-************************************************************************--Note [Adding an equality to the InertCans]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When adding an equality to the inerts:--* Split [WD] into [W] and [D] if the inerts can rewrite the latter;- done by maybeEmitShadow.--* Kick out any constraints that can be rewritten by the thing- we are adding. Done by kickOutRewritable.--* Note that unifying a:=ty, is like adding [G] a~ty; just use- kickOutRewritable with Nominal, Given. See kickOutAfterUnification.--Note [Kicking out CFunEqCan for fundeps]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider:- New: [D] fmv1 ~ fmv2- Inert: [W] F alpha ~ fmv1- [W] F beta ~ fmv2--where F is injective. The new (derived) equality certainly can't-rewrite the inerts. But we *must* kick out the first one, to get:-- New: [W] F alpha ~ fmv1- Inert: [W] F beta ~ fmv2- [D] fmv1 ~ fmv2--and now improvement will discover [D] alpha ~ beta. This is important;-eg in #9587.--So in kickOutRewritable we look at all the tyvars of the-CFunEqCan, including the fsk.--}--addInertCan :: Ct -> TcS () -- Constraints *other than* equalities--- Precondition: item /is/ canonical--- See Note [Adding an equality to the InertCans]-addInertCan ct- = do { traceTcS "insertInertCan {" $- text "Trying to insert new inert item:" <+> ppr ct-- ; ics <- getInertCans- ; ct <- maybeEmitShadow ics ct- ; ics <- maybeKickOut ics ct- ; setInertCans (add_item ics ct)-- ; traceTcS "addInertCan }" $ empty }--maybeKickOut :: InertCans -> Ct -> TcS InertCans--- For a CTyEqCan, kick out any inert that can be rewritten by the CTyEqCan-maybeKickOut ics ct- | CTyEqCan { cc_tyvar = tv, cc_ev = ev, cc_eq_rel = eq_rel } <- ct- = do { (_, ics') <- kickOutRewritable (ctEvFlavour ev, eq_rel) tv ics- ; return ics' }- | otherwise- = return ics--add_item :: InertCans -> Ct -> InertCans-add_item ics item@(CFunEqCan { cc_fun = tc, cc_tyargs = tys })- = ics { inert_funeqs = insertFunEq (inert_funeqs ics) tc tys item }--add_item ics item@(CTyEqCan { cc_tyvar = tv, cc_ev = ev })- = ics { inert_eqs = addTyEq (inert_eqs ics) tv item- , inert_count = bumpUnsolvedCount ev (inert_count ics) }--add_item ics@(IC { inert_irreds = irreds, inert_count = count })- item@(CIrredCan { cc_ev = ev, cc_status = status })- = ics { inert_irreds = irreds `Bag.snocBag` item- , inert_count = case status of- InsolubleCIS -> count- _ -> bumpUnsolvedCount ev count }- -- inert_count does not include insolubles---add_item ics item@(CDictCan { cc_ev = ev, cc_class = cls, cc_tyargs = tys })- = ics { inert_dicts = addDict (inert_dicts ics) cls tys item- , inert_count = bumpUnsolvedCount ev (inert_count ics) }--add_item _ item- = pprPanic "upd_inert set: can't happen! Inserting " $- ppr item -- Can't be CNonCanonical because they only land in inert_irreds--bumpUnsolvedCount :: CtEvidence -> Int -> Int-bumpUnsolvedCount ev n | isWanted ev = n+1- | otherwise = n---------------------------------------------kickOutRewritable :: CtFlavourRole -- Flavour/role of the equality that- -- is being added to the inert set- -> TcTyVar -- The new equality is tv ~ ty- -> InertCans- -> TcS (Int, InertCans)-kickOutRewritable new_fr new_tv ics- = do { let (kicked_out, ics') = kick_out_rewritable new_fr new_tv ics- n_kicked = workListSize kicked_out-- ; unless (n_kicked == 0) $- do { updWorkListTcS (appendWorkList kicked_out)- ; csTraceTcS $- hang (text "Kick out, tv =" <+> ppr new_tv)- 2 (vcat [ text "n-kicked =" <+> int n_kicked- , text "kicked_out =" <+> ppr kicked_out- , text "Residual inerts =" <+> ppr ics' ]) }-- ; return (n_kicked, ics') }--kick_out_rewritable :: CtFlavourRole -- Flavour/role of the equality that- -- is being added to the inert set- -> TcTyVar -- The new equality is tv ~ ty- -> InertCans- -> (WorkList, InertCans)--- See Note [kickOutRewritable]-kick_out_rewritable new_fr new_tv- ics@(IC { inert_eqs = tv_eqs- , inert_dicts = dictmap- , inert_safehask = safehask- , inert_funeqs = funeqmap- , inert_irreds = irreds- , inert_insts = old_insts- , inert_count = n })- | not (new_fr `eqMayRewriteFR` new_fr)- = (emptyWorkList, ics)- -- If new_fr can't rewrite itself, it can't rewrite- -- anything else, so no need to kick out anything.- -- (This is a common case: wanteds can't rewrite wanteds)- -- Lemma (L2) in Note [Extending the inert equalities]-- | otherwise- = (kicked_out, inert_cans_in)- where- inert_cans_in = IC { inert_eqs = tv_eqs_in- , inert_dicts = dicts_in- , inert_safehask = safehask -- ??- , inert_funeqs = feqs_in- , inert_irreds = irs_in- , inert_insts = insts_in- , inert_count = n - workListWantedCount kicked_out }-- kicked_out :: WorkList- -- NB: use extendWorkList to ensure that kicked-out equalities get priority- -- See Note [Prioritise equalities] (Kick-out).- -- The irreds may include non-canonical (hetero-kinded) equality- -- constraints, which perhaps may have become soluble after new_tv- -- is substituted; ditto the dictionaries, which may include (a~b)- -- or (a~~b) constraints.- kicked_out = foldr extendWorkListCt- (emptyWorkList { wl_eqs = tv_eqs_out- , wl_funeqs = feqs_out })- ((dicts_out `andCts` irs_out)- `extendCtsList` insts_out)-- (tv_eqs_out, tv_eqs_in) = foldDVarEnv kick_out_eqs ([], emptyDVarEnv) tv_eqs- (feqs_out, feqs_in) = partitionFunEqs kick_out_ct funeqmap- -- See Note [Kicking out CFunEqCan for fundeps]- (dicts_out, dicts_in) = partitionDicts kick_out_ct dictmap- (irs_out, irs_in) = partitionBag kick_out_ct irreds- -- Kick out even insolubles: See Note [Rewrite insolubles]- -- Of course we must kick out irreducibles like (c a), in case- -- we can rewrite 'c' to something more useful-- -- Kick-out for inert instances- -- See Note [Quantified constraints] in GHC.Tc.Solver.Canonical- insts_out :: [Ct]- insts_in :: [QCInst]- (insts_out, insts_in)- | fr_may_rewrite (Given, NomEq) -- All the insts are Givens- = partitionWith kick_out_qci old_insts- | otherwise- = ([], old_insts)- kick_out_qci qci- | let ev = qci_ev qci- , fr_can_rewrite_ty NomEq (ctEvPred (qci_ev qci))- = Left (mkNonCanonical ev)- | otherwise- = Right qci-- (_, new_role) = new_fr-- fr_can_rewrite_ty :: EqRel -> Type -> Bool- fr_can_rewrite_ty role ty = anyRewritableTyVar False role- fr_can_rewrite_tv ty- fr_can_rewrite_tv :: EqRel -> TyVar -> Bool- fr_can_rewrite_tv role tv = new_role `eqCanRewrite` role- && tv == new_tv-- fr_may_rewrite :: CtFlavourRole -> Bool- fr_may_rewrite fs = new_fr `eqMayRewriteFR` fs- -- Can the new item rewrite the inert item?-- kick_out_ct :: Ct -> Bool- -- Kick it out if the new CTyEqCan can rewrite the inert one- -- See Note [kickOutRewritable]- kick_out_ct ct | let fs@(_,role) = ctFlavourRole ct- = fr_may_rewrite fs- && fr_can_rewrite_ty role (ctPred ct)- -- False: ignore casts and coercions- -- NB: this includes the fsk of a CFunEqCan. It can't- -- actually be rewritten, but we need to kick it out- -- so we get to take advantage of injectivity- -- See Note [Kicking out CFunEqCan for fundeps]-- kick_out_eqs :: EqualCtList -> ([Ct], DTyVarEnv EqualCtList)- -> ([Ct], DTyVarEnv EqualCtList)- kick_out_eqs eqs (acc_out, acc_in)- = (eqs_out ++ acc_out, case eqs_in of- [] -> acc_in- (eq1:_) -> extendDVarEnv acc_in (cc_tyvar eq1) eqs_in)- where- (eqs_out, eqs_in) = partition kick_out_eq eqs-- -- Implements criteria K1-K3 in Note [Extending the inert equalities]- kick_out_eq (CTyEqCan { cc_tyvar = tv, cc_rhs = rhs_ty- , cc_ev = ev, cc_eq_rel = eq_rel })- | not (fr_may_rewrite fs)- = False -- Keep it in the inert set if the new thing can't rewrite it-- -- Below here (fr_may_rewrite fs) is True- | tv == new_tv = True -- (K1)- | kick_out_for_inertness = True- | kick_out_for_completeness = True- | otherwise = False-- where- fs = (ctEvFlavour ev, eq_rel)- kick_out_for_inertness- = (fs `eqMayRewriteFR` fs) -- (K2a)- && not (fs `eqMayRewriteFR` new_fr) -- (K2b)- && fr_can_rewrite_ty eq_rel rhs_ty -- (K2d)- -- (K2c) is guaranteed by the first guard of keep_eq-- kick_out_for_completeness- = case eq_rel of- NomEq -> rhs_ty `eqType` mkTyVarTy new_tv- ReprEq -> isTyVarHead new_tv rhs_ty-- kick_out_eq ct = pprPanic "keep_eq" (ppr ct)--kickOutAfterUnification :: TcTyVar -> TcS Int-kickOutAfterUnification new_tv- = do { ics <- getInertCans- ; (n_kicked, ics2) <- kickOutRewritable (Given,NomEq)- new_tv ics- -- Given because the tv := xi is given; NomEq because- -- only nominal equalities are solved by unification-- ; setInertCans ics2- ; return n_kicked }---- See Wrinkle (2b) in Note [Equalities with incompatible kinds] in "GHC.Tc.Solver.Canonical"-kickOutAfterFillingCoercionHole :: CoercionHole -> TcS ()-kickOutAfterFillingCoercionHole hole- = do { ics <- getInertCans- ; let (kicked_out, ics') = kick_out ics- n_kicked = workListSize kicked_out-- ; unless (n_kicked == 0) $- do { updWorkListTcS (appendWorkList kicked_out)- ; csTraceTcS $- hang (text "Kick out, hole =" <+> ppr hole)- 2 (vcat [ text "n-kicked =" <+> int n_kicked- , text "kicked_out =" <+> ppr kicked_out- , text "Residual inerts =" <+> ppr ics' ]) }-- ; setInertCans ics' }- where- kick_out :: InertCans -> (WorkList, InertCans)- kick_out ics@(IC { inert_irreds = irreds })- = let (to_kick, to_keep) = partitionBag kick_ct irreds-- kicked_out = extendWorkListCts (bagToList to_kick) emptyWorkList- ics' = ics { inert_irreds = to_keep }- in- (kicked_out, ics')-- kick_ct :: Ct -> Bool- -- This is not particularly efficient. Ways to do better:- -- 1) Have a custom function that looks for a coercion hole and returns a Bool- -- 2) Keep co-hole-blocked constraints in a separate part of the inert set,- -- keyed by their co-hole. (Is it possible for more than one co-hole to be- -- in a constraint? I doubt it.)- kick_ct (CIrredCan { cc_ev = ev, cc_status = BlockedCIS })- = coHoleCoVar hole `elemVarSet` tyCoVarsOfType (ctEvPred ev)- kick_ct _other = False--{- Note [kickOutRewritable]-~~~~~~~~~~~~~~~~~~~~~~~~~~~-See also Note [inert_eqs: the inert equalities].--When we add a new inert equality (a ~N ty) to the inert set,-we must kick out any inert items that could be rewritten by the-new equality, to maintain the inert-set invariants.-- - We want to kick out an existing inert constraint if- a) the new constraint can rewrite the inert one- b) 'a' is free in the inert constraint (so that it *will*)- rewrite it if we kick it out.-- For (b) we use tyCoVarsOfCt, which returns the type variables /and- the kind variables/ that are directly visible in the type. Hence- we will have exposed all the rewriting we care about to make the- most precise kinds visible for matching classes etc. No need to- kick out constraints that mention type variables whose kinds- contain this variable!-- - A Derived equality can kick out [D] constraints in inert_eqs,- inert_dicts, inert_irreds etc.-- - We don't kick out constraints from inert_solved_dicts, and- inert_solved_funeqs optimistically. But when we lookup we have to- take the substitution into account---Note [Rewrite insolubles]-~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we have an insoluble alpha ~ [alpha], which is insoluble-because an occurs check. And then we unify alpha := [Int]. Then we-really want to rewrite the insoluble to [Int] ~ [[Int]]. Now it can-be decomposed. Otherwise we end up with a "Can't match [Int] ~-[[Int]]" which is true, but a bit confusing because the outer type-constructors match.--Hence:- * In the main simplifier loops in GHC.Tc.Solver (solveWanteds,- simpl_loop), we feed the insolubles in solveSimpleWanteds,- so that they get rewritten (albeit not solved).-- * We kick insolubles out of the inert set, if they can be- rewritten (see GHC.Tc.Solver.Monad.kick_out_rewritable)-- * We rewrite those insolubles in GHC.Tc.Solver.Canonical.- See Note [Make sure that insolubles are fully rewritten]--}-------------------addInertSafehask :: InertCans -> Ct -> InertCans-addInertSafehask ics item@(CDictCan { cc_class = cls, cc_tyargs = tys })- = ics { inert_safehask = addDict (inert_dicts ics) cls tys item }--addInertSafehask _ item- = pprPanic "addInertSafehask: can't happen! Inserting " $ ppr item--insertSafeOverlapFailureTcS :: InstanceWhat -> Ct -> TcS ()--- See Note [Safe Haskell Overlapping Instances Implementation] in GHC.Tc.Solver-insertSafeOverlapFailureTcS what item- | safeOverlap what = return ()- | otherwise = updInertCans (\ics -> addInertSafehask ics item)--getSafeOverlapFailures :: TcS Cts--- See Note [Safe Haskell Overlapping Instances Implementation] in GHC.Tc.Solver-getSafeOverlapFailures- = do { IC { inert_safehask = safehask } <- getInertCans- ; return $ foldDicts consCts safehask emptyCts }-----------------addSolvedDict :: InstanceWhat -> CtEvidence -> Class -> [Type] -> TcS ()--- Conditionally add a new item in the solved set of the monad--- See Note [Solved dictionaries]-addSolvedDict what item cls tys- | isWanted item- , instanceReturnsDictCon what- = do { traceTcS "updSolvedSetTcs:" $ ppr item- ; updInertTcS $ \ ics ->- ics { inert_solved_dicts = addDict (inert_solved_dicts ics) cls tys item } }- | otherwise- = return ()--getSolvedDicts :: TcS (DictMap CtEvidence)-getSolvedDicts = do { ics <- getTcSInerts; return (inert_solved_dicts ics) }--setSolvedDicts :: DictMap CtEvidence -> TcS ()-setSolvedDicts solved_dicts- = updInertTcS $ \ ics ->- ics { inert_solved_dicts = solved_dicts }---{- *********************************************************************-* *- Other inert-set operations-* *-********************************************************************* -}--updInertTcS :: (InertSet -> InertSet) -> TcS ()--- Modify the inert set with the supplied function-updInertTcS upd_fn- = do { is_var <- getTcSInertsRef- ; wrapTcS (do { curr_inert <- TcM.readTcRef is_var- ; TcM.writeTcRef is_var (upd_fn curr_inert) }) }--getInertCans :: TcS InertCans-getInertCans = do { inerts <- getTcSInerts; return (inert_cans inerts) }--setInertCans :: InertCans -> TcS ()-setInertCans ics = updInertTcS $ \ inerts -> inerts { inert_cans = ics }--updRetInertCans :: (InertCans -> (a, InertCans)) -> TcS a--- Modify the inert set with the supplied function-updRetInertCans upd_fn- = do { is_var <- getTcSInertsRef- ; wrapTcS (do { inerts <- TcM.readTcRef is_var- ; let (res, cans') = upd_fn (inert_cans inerts)- ; TcM.writeTcRef is_var (inerts { inert_cans = cans' })- ; return res }) }--updInertCans :: (InertCans -> InertCans) -> TcS ()--- Modify the inert set with the supplied function-updInertCans upd_fn- = updInertTcS $ \ inerts -> inerts { inert_cans = upd_fn (inert_cans inerts) }--updInertDicts :: (DictMap Ct -> DictMap Ct) -> TcS ()--- Modify the inert set with the supplied function-updInertDicts upd_fn- = updInertCans $ \ ics -> ics { inert_dicts = upd_fn (inert_dicts ics) }--updInertSafehask :: (DictMap Ct -> DictMap Ct) -> TcS ()--- Modify the inert set with the supplied function-updInertSafehask upd_fn- = updInertCans $ \ ics -> ics { inert_safehask = upd_fn (inert_safehask ics) }--updInertFunEqs :: (FunEqMap Ct -> FunEqMap Ct) -> TcS ()--- Modify the inert set with the supplied function-updInertFunEqs upd_fn- = updInertCans $ \ ics -> ics { inert_funeqs = upd_fn (inert_funeqs ics) }--updInertIrreds :: (Cts -> Cts) -> TcS ()--- Modify the inert set with the supplied function-updInertIrreds upd_fn- = updInertCans $ \ ics -> ics { inert_irreds = upd_fn (inert_irreds ics) }--getInertEqs :: TcS (DTyVarEnv EqualCtList)-getInertEqs = do { inert <- getInertCans; return (inert_eqs inert) }--getInertInsols :: TcS Cts--- Returns insoluble equality constraints--- specifically including Givens-getInertInsols = do { inert <- getInertCans- ; return (filterBag insolubleEqCt (inert_irreds inert)) }--getInertGivens :: TcS [Ct]--- Returns the Given constraints in the inert set,--- with type functions *not* unflattened-getInertGivens- = do { inerts <- getInertCans- ; let all_cts = foldDicts (:) (inert_dicts inerts)- $ foldFunEqs (:) (inert_funeqs inerts)- $ concat (dVarEnvElts (inert_eqs inerts))- ; return (filter isGivenCt all_cts) }--getPendingGivenScs :: TcS [Ct]--- Find all inert Given dictionaries, or quantified constraints,--- whose cc_pend_sc flag is True--- and that belong to the current level--- Set their cc_pend_sc flag to False in the inert set, and return that Ct-getPendingGivenScs = do { lvl <- getTcLevel- ; updRetInertCans (get_sc_pending lvl) }--get_sc_pending :: TcLevel -> InertCans -> ([Ct], InertCans)-get_sc_pending this_lvl ic@(IC { inert_dicts = dicts, inert_insts = insts })- = ASSERT2( all isGivenCt sc_pending, ppr sc_pending )- -- When getPendingScDics is called,- -- there are never any Wanteds in the inert set- (sc_pending, ic { inert_dicts = dicts', inert_insts = insts' })- where- sc_pending = sc_pend_insts ++ sc_pend_dicts-- sc_pend_dicts = foldDicts get_pending dicts []- dicts' = foldr add dicts sc_pend_dicts-- (sc_pend_insts, insts') = mapAccumL get_pending_inst [] insts-- get_pending :: Ct -> [Ct] -> [Ct] -- Get dicts with cc_pend_sc = True- -- but flipping the flag- get_pending dict dicts- | Just dict' <- isPendingScDict dict- , belongs_to_this_level (ctEvidence dict)- = dict' : dicts- | otherwise- = dicts-- add :: Ct -> DictMap Ct -> DictMap Ct- add ct@(CDictCan { cc_class = cls, cc_tyargs = tys }) dicts- = addDict dicts cls tys ct- add ct _ = pprPanic "getPendingScDicts" (ppr ct)-- get_pending_inst :: [Ct] -> QCInst -> ([Ct], QCInst)- get_pending_inst cts qci@(QCI { qci_ev = ev })- | Just qci' <- isPendingScInst qci- , belongs_to_this_level ev- = (CQuantCan qci' : cts, qci')- | otherwise- = (cts, qci)-- belongs_to_this_level ev = ctLocLevel (ctEvLoc ev) == this_lvl- -- We only want Givens from this level; see (3a) in- -- Note [The superclass story] in GHC.Tc.Solver.Canonical--getUnsolvedInerts :: TcS ( Bag Implication- , Cts -- Tyvar eqs: a ~ ty- , Cts -- Fun eqs: F a ~ ty- , Cts ) -- All others--- Return all the unsolved [Wanted] or [Derived] constraints------ Post-condition: the returned simple constraints are all fully zonked--- (because they come from the inert set)--- the unsolved implics may not be-getUnsolvedInerts- = do { IC { inert_eqs = tv_eqs- , inert_funeqs = fun_eqs- , inert_irreds = irreds- , inert_dicts = idicts- } <- getInertCans-- ; let unsolved_tv_eqs = foldTyEqs add_if_unsolved tv_eqs emptyCts- unsolved_fun_eqs = foldFunEqs add_if_wanted fun_eqs emptyCts- unsolved_irreds = Bag.filterBag is_unsolved irreds- unsolved_dicts = foldDicts add_if_unsolved idicts emptyCts- unsolved_others = unsolved_irreds `unionBags` unsolved_dicts-- ; implics <- getWorkListImplics-- ; traceTcS "getUnsolvedInerts" $- vcat [ text " tv eqs =" <+> ppr unsolved_tv_eqs- , text "fun eqs =" <+> ppr unsolved_fun_eqs- , text "others =" <+> ppr unsolved_others- , text "implics =" <+> ppr implics ]-- ; return ( implics, unsolved_tv_eqs, unsolved_fun_eqs, unsolved_others) }- where- add_if_unsolved :: Ct -> Cts -> Cts- add_if_unsolved ct cts | is_unsolved ct = ct `consCts` cts- | otherwise = cts-- is_unsolved ct = not (isGivenCt ct) -- Wanted or Derived-- -- For CFunEqCans we ignore the Derived ones, and keep- -- only the Wanteds for flattening. The Derived ones- -- share a unification variable with the corresponding- -- Wanted, so we definitely don't want to participate- -- in unflattening- -- See Note [Type family equations]- add_if_wanted ct cts | isWantedCt ct = ct `consCts` cts- | otherwise = cts--isInInertEqs :: DTyVarEnv EqualCtList -> TcTyVar -> TcType -> Bool--- True if (a ~N ty) is in the inert set, in either Given or Wanted-isInInertEqs eqs tv rhs- = case lookupDVarEnv eqs tv of- Nothing -> False- Just cts -> any (same_pred rhs) cts- where- same_pred rhs ct- | CTyEqCan { cc_rhs = rhs2, cc_eq_rel = eq_rel } <- ct- , NomEq <- eq_rel- , rhs `eqType` rhs2 = True- | otherwise = False--getNoGivenEqs :: TcLevel -- TcLevel of this implication- -> [TcTyVar] -- Skolems of this implication- -> TcS ( Bool -- True <=> definitely no residual given equalities- , Cts ) -- Insoluble equalities arising from givens--- See Note [When does an implication have given equalities?]-getNoGivenEqs tclvl skol_tvs- = do { inerts@(IC { inert_eqs = ieqs, inert_irreds = irreds })- <- getInertCans- ; let has_given_eqs = foldr ((||) . ct_given_here) False irreds- || anyDVarEnv eqs_given_here ieqs- insols = filterBag insolubleEqCt irreds- -- Specifically includes ones that originated in some- -- outer context but were refined to an insoluble by- -- a local equality; so do /not/ add ct_given_here.-- ; traceTcS "getNoGivenEqs" $- vcat [ if has_given_eqs then text "May have given equalities"- else text "No given equalities"- , text "Skols:" <+> ppr skol_tvs- , text "Inerts:" <+> ppr inerts- , text "Insols:" <+> ppr insols]- ; return (not has_given_eqs, insols) }- where- eqs_given_here :: EqualCtList -> Bool- eqs_given_here [ct@(CTyEqCan { cc_tyvar = tv })]- -- Givens are always a singleton- = not (skolem_bound_here tv) && ct_given_here ct- eqs_given_here _ = False-- ct_given_here :: Ct -> Bool- -- True for a Given bound by the current implication,- -- i.e. the current level- ct_given_here ct = isGiven ev- && tclvl == ctLocLevel (ctEvLoc ev)- where- ev = ctEvidence ct-- skol_tv_set = mkVarSet skol_tvs- skolem_bound_here tv -- See Note [Let-bound skolems]- = case tcTyVarDetails tv of- SkolemTv {} -> tv `elemVarSet` skol_tv_set- _ -> False---- | Returns Given constraints that might,--- potentially, match the given pred. This is used when checking to see if a--- Given might overlap with an instance. See Note [Instance and Given overlap]--- in "GHC.Tc.Solver.Interact"-matchableGivens :: CtLoc -> PredType -> InertSet -> Cts-matchableGivens loc_w pred_w (IS { inert_cans = inert_cans })- = filterBag matchable_given all_relevant_givens- where- -- just look in class constraints and irreds. matchableGivens does get called- -- for ~R constraints, but we don't need to look through equalities, because- -- canonical equalities are used for rewriting. We'll only get caught by- -- non-canonical -- that is, irreducible -- equalities.- all_relevant_givens :: Cts- all_relevant_givens- | Just (clas, _) <- getClassPredTys_maybe pred_w- = findDictsByClass (inert_dicts inert_cans) clas- `unionBags` inert_irreds inert_cans- | otherwise- = inert_irreds inert_cans-- matchable_given :: Ct -> Bool- matchable_given ct- | CtGiven { ctev_loc = loc_g, ctev_pred = pred_g } <- ctEvidence ct- = mightMatchLater pred_g loc_g pred_w loc_w-- | otherwise- = False--mightMatchLater :: TcPredType -> CtLoc -> TcPredType -> CtLoc -> Bool-mightMatchLater given_pred given_loc wanted_pred wanted_loc- = not (prohibitedSuperClassSolve given_loc wanted_loc)- && isJust (tcUnifyTys bind_meta_tv [given_pred] [wanted_pred])- where- bind_meta_tv :: TcTyVar -> BindFlag- -- Any meta tyvar may be unified later, so we treat it as- -- bindable when unifying with givens. That ensures that we- -- conservatively assume that a meta tyvar might get unified with- -- something that matches the 'given', until demonstrated- -- otherwise. More info in Note [Instance and Given overlap]- -- in GHC.Tc.Solver.Interact- bind_meta_tv tv | isMetaTyVar tv- , not (isFskTyVar tv) = BindMe- | otherwise = Skolem--prohibitedSuperClassSolve :: CtLoc -> CtLoc -> Bool--- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance-prohibitedSuperClassSolve from_loc solve_loc- | GivenOrigin (InstSC given_size) <- ctLocOrigin from_loc- , ScOrigin wanted_size <- ctLocOrigin solve_loc- = given_size >= wanted_size- | otherwise- = False--{- Note [Unsolved Derived equalities]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-In getUnsolvedInerts, we return a derived equality from the inert_eqs-because it is a candidate for floating out of this implication. We-only float equalities with a meta-tyvar on the left, so we only pull-those out here.--Note [When does an implication have given equalities?]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider an implication- beta => alpha ~ Int-where beta is a unification variable that has already been unified-to () in an outer scope. Then we can float the (alpha ~ Int) out-just fine. So when deciding whether the givens contain an equality,-we should canonicalise first, rather than just looking at the original-givens (#8644).--So we simply look at the inert, canonical Givens and see if there are-any equalities among them, the calculation of has_given_eqs. There-are some wrinkles:-- * We must know which ones are bound in *this* implication and which- are bound further out. We can find that out from the TcLevel- of the Given, which is itself recorded in the tcl_tclvl field- of the TcLclEnv stored in the Given (ev_given_here).-- What about interactions between inner and outer givens?- - Outer given is rewritten by an inner given, then there must- have been an inner given equality, hence the “given-eq” flag- will be true anyway.-- - Inner given rewritten by outer, retains its level (ie. The inner one)-- * We must take account of *potential* equalities, like the one above:- beta => ...blah...- If we still don't know what beta is, we conservatively treat it as potentially- becoming an equality. Hence including 'irreds' in the calculation or has_given_eqs.-- * When flattening givens, we generate Given equalities like- <F [a]> : F [a] ~ f,- with Refl evidence, and we *don't* want those to count as an equality- in the givens! After all, the entire flattening business is just an- internal matter, and the evidence does not mention any of the 'givens'- of this implication. So we do not treat inert_funeqs as a 'given equality'.-- * See Note [Let-bound skolems] for another wrinkle-- * We do *not* need to worry about representational equalities, because- these do not affect the ability to float constraints.--Note [Let-bound skolems]-~~~~~~~~~~~~~~~~~~~~~~~~-If * the inert set contains a canonical Given CTyEqCan (a ~ ty)-and * 'a' is a skolem bound in this very implication,--then:-a) The Given is pretty much a let-binding, like- f :: (a ~ b->c) => a -> a- Here the equality constraint is like saying- let a = b->c in ...- It is not adding any new, local equality information,- and hence can be ignored by has_given_eqs--b) 'a' will have been completely substituted out in the inert set,- so we can safely discard it. Notably, it doesn't need to be- returned as part of 'fsks'--For an example, see #9211.--See also GHC.Tc.Utils.Unify Note [Deeper level on the left] for how we ensure-that the right variable is on the left of the equality when both are-tyvars.--You might wonder whether the skokem really needs to be bound "in the-very same implication" as the equuality constraint.-(c.f. #15009) Consider this:-- data S a where- MkS :: (a ~ Int) => S a-- g :: forall a. S a -> a -> blah- g x y = let h = \z. ( z :: Int- , case x of- MkS -> [y,z])- in ...--From the type signature for `g`, we get `y::a` . Then when we-encounter the `\z`, we'll assign `z :: alpha[1]`, say. Next, from the-body of the lambda we'll get-- [W] alpha[1] ~ Int -- From z::Int- [W] forall[2]. (a ~ Int) => [W] alpha[1] ~ a -- From [y,z]--Now, suppose we decide to float `alpha ~ a` out of the implication-and then unify `alpha := a`. Now we are stuck! But if treat-`alpha ~ Int` first, and unify `alpha := Int`, all is fine.-But we absolutely cannot float that equality or we will get stuck.--}--removeInertCts :: [Ct] -> InertCans -> InertCans--- ^ Remove inert constraints from the 'InertCans', for use when a--- typechecker plugin wishes to discard a given.-removeInertCts cts icans = foldl' removeInertCt icans cts--removeInertCt :: InertCans -> Ct -> InertCans-removeInertCt is ct =- case ct of-- CDictCan { cc_class = cl, cc_tyargs = tys } ->- is { inert_dicts = delDict (inert_dicts is) cl tys }-- CFunEqCan { cc_fun = tf, cc_tyargs = tys } ->- is { inert_funeqs = delFunEq (inert_funeqs is) tf tys }-- CTyEqCan { cc_tyvar = x, cc_rhs = ty } ->- is { inert_eqs = delTyEq (inert_eqs is) x ty }-- CQuantCan {} -> panic "removeInertCt: CQuantCan"- CIrredCan {} -> panic "removeInertCt: CIrredEvCan"- CNonCanonical {} -> panic "removeInertCt: CNonCanonical"--lookupFlatCache :: TyCon -> [Type] -> TcS (Maybe (TcCoercion, TcType, CtFlavour))-lookupFlatCache fam_tc tys- = do { IS { inert_flat_cache = flat_cache- , inert_cans = IC { inert_funeqs = inert_funeqs } } <- getTcSInerts- ; return (firstJusts [lookup_inerts inert_funeqs,- lookup_flats flat_cache]) }- where- lookup_inerts inert_funeqs- | Just (CFunEqCan { cc_ev = ctev, cc_fsk = fsk })- <- findFunEq inert_funeqs fam_tc tys- = Just (ctEvCoercion ctev, mkTyVarTy fsk, ctEvFlavour ctev)- | otherwise = Nothing-- lookup_flats flat_cache = findExactFunEq flat_cache fam_tc tys---lookupInInerts :: CtLoc -> TcPredType -> TcS (Maybe CtEvidence)--- Is this exact predicate type cached in the solved or canonicals of the InertSet?-lookupInInerts loc pty- | ClassPred cls tys <- classifyPredType pty- = do { inerts <- getTcSInerts- ; return (lookupSolvedDict inerts loc cls tys `mplus`- lookupInertDict (inert_cans inerts) loc cls tys) }- | otherwise -- NB: No caching for equalities, IPs, holes, or errors- = return Nothing---- | Look up a dictionary inert.-lookupInertDict :: InertCans -> CtLoc -> Class -> [Type] -> Maybe CtEvidence-lookupInertDict (IC { inert_dicts = dicts }) loc cls tys- = case findDict dicts loc cls tys of- Just ct -> Just (ctEvidence ct)- _ -> Nothing---- | Look up a solved inert.-lookupSolvedDict :: InertSet -> CtLoc -> Class -> [Type] -> Maybe CtEvidence--- Returns just if exactly this predicate type exists in the solved.-lookupSolvedDict (IS { inert_solved_dicts = solved }) loc cls tys- = case findDict solved loc cls tys of- Just ev -> Just ev- _ -> Nothing--{- *********************************************************************-* *- Irreds-* *-********************************************************************* -}--foldIrreds :: (Ct -> b -> b) -> Cts -> b -> b-foldIrreds k irreds z = foldr k z irreds---{- *********************************************************************-* *- TcAppMap-* *-************************************************************************--Note [Use loose types in inert set]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Whenever we are looking up an inert dictionary (CDictCan) or function-equality (CFunEqCan), we use a TcAppMap, which uses the Unique of the-class/type family tycon and then a trie which maps the arguments. This-trie does *not* need to match the kinds of the arguments; this Note-explains why.--Consider the types ty0 = (T ty1 ty2 ty3 ty4) and ty0' = (T ty1' ty2' ty3' ty4'),-where ty4 and ty4' have different kinds. Let's further assume that both types-ty0 and ty0' are well-typed. Because the kind of T is closed, it must be that-one of the ty1..ty3 does not match ty1'..ty3' (and that the kind of the fourth-argument to T is dependent on whichever one changed). Since we are matching-all arguments, during the inert-set lookup, we know that ty1..ty3 do indeed-match ty1'..ty3'. Therefore, the kind of ty4 and ty4' must match, too ---without ever looking at it.--Accordingly, we use LooseTypeMap, which skips the kind check when looking-up a type. I (Richard E) believe this is just an optimization, and that-looking at kinds would be harmless.---}--type TcAppMap a = UniqDFM Unique (ListMap LooseTypeMap a)- -- Indexed by tycon then the arg types, using "loose" matching, where- -- we don't require kind equality. This allows, for example, (a |> co)- -- to match (a).- -- See Note [Use loose types in inert set]- -- Used for types and classes; hence UniqDFM- -- See Note [foldTM determinism] for why we use UniqDFM here--isEmptyTcAppMap :: TcAppMap a -> Bool-isEmptyTcAppMap m = isNullUDFM m--emptyTcAppMap :: TcAppMap a-emptyTcAppMap = emptyUDFM--findTcApp :: TcAppMap a -> Unique -> [Type] -> Maybe a-findTcApp m u tys = do { tys_map <- lookupUDFM m u- ; lookupTM tys tys_map }--delTcApp :: TcAppMap a -> Unique -> [Type] -> TcAppMap a-delTcApp m cls tys = adjustUDFM (deleteTM tys) m cls--insertTcApp :: TcAppMap a -> Unique -> [Type] -> a -> TcAppMap a-insertTcApp m cls tys ct = alterUDFM alter_tm m cls- where- alter_tm mb_tm = Just (insertTM tys ct (mb_tm `orElse` emptyTM))---- mapTcApp :: (a->b) -> TcAppMap a -> TcAppMap b--- mapTcApp f = mapUDFM (mapTM f)--filterTcAppMap :: (Ct -> Bool) -> TcAppMap Ct -> TcAppMap Ct-filterTcAppMap f m- = mapUDFM do_tm m- where- do_tm tm = foldTM insert_mb tm emptyTM- insert_mb ct tm- | f ct = insertTM tys ct tm- | otherwise = tm- where- tys = case ct of- CFunEqCan { cc_tyargs = tys } -> tys- CDictCan { cc_tyargs = tys } -> tys- _ -> pprPanic "filterTcAppMap" (ppr ct)--tcAppMapToBag :: TcAppMap a -> Bag a-tcAppMapToBag m = foldTcAppMap consBag m emptyBag--foldTcAppMap :: (a -> b -> b) -> TcAppMap a -> b -> b-foldTcAppMap k m z = foldUDFM (foldTM k) z m---{- *********************************************************************-* *- DictMap-* *-********************************************************************* -}---{- Note [Tuples hiding implicit parameters]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider- f,g :: (?x::Int, C a) => a -> a- f v = let ?x = 4 in g v--The call to 'g' gives rise to a Wanted constraint (?x::Int, C a).-We must /not/ solve this from the Given (?x::Int, C a), because of-the intervening binding for (?x::Int). #14218.--We deal with this by arranging that we always fail when looking up a-tuple constraint that hides an implicit parameter. Not that this applies- * both to the inert_dicts (lookupInertDict)- * and to the solved_dicts (looukpSolvedDict)-An alternative would be not to extend these sets with such tuple-constraints, but it seemed more direct to deal with the lookup.--Note [Solving CallStack constraints]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose f :: HasCallStack => blah. Then--* Each call to 'f' gives rise to- [W] s1 :: IP "callStack" CallStack -- CtOrigin = OccurrenceOf f- with a CtOrigin that says "OccurrenceOf f".- Remember that HasCallStack is just shorthand for- IP "callStack CallStack- See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence--* We cannonicalise such constraints, in GHC.Tc.Solver.Canonical.canClassNC, by- pushing the call-site info on the stack, and changing the CtOrigin- to record that has been done.- Bind: s1 = pushCallStack <site-info> s2- [W] s2 :: IP "callStack" CallStack -- CtOrigin = IPOccOrigin--* Then, and only then, we can solve the constraint from an enclosing- Given.--So we must be careful /not/ to solve 's1' from the Givens. Again,-we ensure this by arranging that findDict always misses when looking-up souch constraints.--}--type DictMap a = TcAppMap a--emptyDictMap :: DictMap a-emptyDictMap = emptyTcAppMap--findDict :: DictMap a -> CtLoc -> Class -> [Type] -> Maybe a-findDict m loc cls tys- | hasIPSuperClasses cls tys -- See Note [Tuples hiding implicit parameters]- = Nothing-- | Just {} <- isCallStackPred cls tys- , OccurrenceOf {} <- ctLocOrigin loc- = Nothing -- See Note [Solving CallStack constraints]-- | otherwise- = findTcApp m (getUnique cls) tys--findDictsByClass :: DictMap a -> Class -> Bag a-findDictsByClass m cls- | Just tm <- lookupUDFM_Directly m (getUnique cls) = foldTM consBag tm emptyBag- | otherwise = emptyBag--delDict :: DictMap a -> Class -> [Type] -> DictMap a-delDict m cls tys = delTcApp m (getUnique cls) tys--addDict :: DictMap a -> Class -> [Type] -> a -> DictMap a-addDict m cls tys item = insertTcApp m (getUnique cls) tys item--addDictsByClass :: DictMap Ct -> Class -> Bag Ct -> DictMap Ct-addDictsByClass m cls items- = addToUDFM_Directly m (getUnique cls) (foldr add emptyTM items)- where- add ct@(CDictCan { cc_tyargs = tys }) tm = insertTM tys ct tm- add ct _ = pprPanic "addDictsByClass" (ppr ct)--filterDicts :: (Ct -> Bool) -> DictMap Ct -> DictMap Ct-filterDicts f m = filterTcAppMap f m--partitionDicts :: (Ct -> Bool) -> DictMap Ct -> (Bag Ct, DictMap Ct)-partitionDicts f m = foldTcAppMap k m (emptyBag, emptyDicts)- where- k ct (yeses, noes) | f ct = (ct `consBag` yeses, noes)- | otherwise = (yeses, add ct noes)- add ct@(CDictCan { cc_class = cls, cc_tyargs = tys }) m- = addDict m cls tys ct- add ct _ = pprPanic "partitionDicts" (ppr ct)--dictsToBag :: DictMap a -> Bag a-dictsToBag = tcAppMapToBag--foldDicts :: (a -> b -> b) -> DictMap a -> b -> b-foldDicts = foldTcAppMap--emptyDicts :: DictMap a-emptyDicts = emptyTcAppMap---{- *********************************************************************-* *- FunEqMap-* *-********************************************************************* -}--type FunEqMap a = TcAppMap a -- A map whose key is a (TyCon, [Type]) pair--emptyFunEqs :: TcAppMap a-emptyFunEqs = emptyTcAppMap--findFunEq :: FunEqMap a -> TyCon -> [Type] -> Maybe a-findFunEq m tc tys = findTcApp m (getUnique tc) tys--funEqsToBag :: FunEqMap a -> Bag a-funEqsToBag m = foldTcAppMap consBag m emptyBag--findFunEqsByTyCon :: FunEqMap a -> TyCon -> [a]--- Get inert function equation constraints that have the given tycon--- in their head. Not that the constraints remain in the inert set.--- We use this to check for derived interactions with built-in type-function--- constructors.-findFunEqsByTyCon m tc- | Just tm <- lookupUDFM m (getUnique tc) = foldTM (:) tm []- | otherwise = []--foldFunEqs :: (a -> b -> b) -> FunEqMap a -> b -> b-foldFunEqs = foldTcAppMap---- mapFunEqs :: (a -> b) -> FunEqMap a -> FunEqMap b--- mapFunEqs = mapTcApp---- filterFunEqs :: (Ct -> Bool) -> FunEqMap Ct -> FunEqMap Ct--- filterFunEqs = filterTcAppMap--insertFunEq :: FunEqMap a -> TyCon -> [Type] -> a -> FunEqMap a-insertFunEq m tc tys val = insertTcApp m (getUnique tc) tys val--partitionFunEqs :: (Ct -> Bool) -> FunEqMap Ct -> ([Ct], FunEqMap Ct)--- Optimise for the case where the predicate is false--- partitionFunEqs is called only from kick-out, and kick-out usually--- kicks out very few equalities, so we want to optimise for that case-partitionFunEqs f m = (yeses, foldr del m yeses)- where- yeses = foldTcAppMap k m []- k ct yeses | f ct = ct : yeses- | otherwise = yeses- del (CFunEqCan { cc_fun = tc, cc_tyargs = tys }) m- = delFunEq m tc tys- del ct _ = pprPanic "partitionFunEqs" (ppr ct)--delFunEq :: FunEqMap a -> TyCon -> [Type] -> FunEqMap a-delFunEq m tc tys = delTcApp m (getUnique tc) tys---------------------------------type ExactFunEqMap a = TyConEnv (ListMap TypeMap a)--emptyExactFunEqs :: ExactFunEqMap a-emptyExactFunEqs = emptyUFM--findExactFunEq :: ExactFunEqMap a -> TyCon -> [Type] -> Maybe a-findExactFunEq m tc tys = do { tys_map <- lookupUFM m tc- ; lookupTM tys tys_map }--insertExactFunEq :: ExactFunEqMap a -> TyCon -> [Type] -> a -> ExactFunEqMap a-insertExactFunEq m tc tys val = alterUFM alter_tm m tc- where alter_tm mb_tm = Just (insertTM tys val (mb_tm `orElse` emptyTM))--{--************************************************************************-* *-* The TcS solver monad *-* *-************************************************************************--Note [The TcS monad]-~~~~~~~~~~~~~~~~~~~~-The TcS monad is a weak form of the main Tc monad--All you can do is- * fail- * allocate new variables- * fill in evidence variables--Filling in a dictionary evidence variable means to create a binding-for it, so TcS carries a mutable location where the binding can be-added. This is initialised from the innermost implication constraint.--}--data TcSEnv- = TcSEnv {- tcs_ev_binds :: EvBindsVar,-- tcs_unified :: IORef Int,- -- The number of unification variables we have filled- -- The important thing is whether it is non-zero-- tcs_count :: IORef Int, -- Global step count-- tcs_inerts :: IORef InertSet, -- Current inert set-- -- The main work-list and the flattening worklist- -- See Note [Work list priorities] and- tcs_worklist :: IORef WorkList -- Current worklist- }------------------newtype TcS a = TcS { unTcS :: TcSEnv -> TcM a } deriving (Functor)--instance Applicative TcS where- pure x = TcS (\_ -> return x)- (<*>) = ap--instance Monad TcS where- m >>= k = TcS (\ebs -> unTcS m ebs >>= \r -> unTcS (k r) ebs)--instance MonadFail TcS where- fail err = TcS (\_ -> fail err)--instance MonadUnique TcS where- getUniqueSupplyM = wrapTcS getUniqueSupplyM--instance HasModule TcS where- getModule = wrapTcS getModule--instance MonadThings TcS where- lookupThing n = wrapTcS (lookupThing n)---- Basic functionality--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-wrapTcS :: TcM a -> TcS a--- Do not export wrapTcS, because it promotes an arbitrary TcM to TcS,--- and TcS is supposed to have limited functionality-wrapTcS = TcS . const -- a TcM action will not use the TcEvBinds--wrapErrTcS :: TcM a -> TcS a--- The thing wrapped should just fail--- There's no static check; it's up to the user--- Having a variant for each error message is too painful-wrapErrTcS = wrapTcS--wrapWarnTcS :: TcM a -> TcS a--- The thing wrapped should just add a warning, or no-op--- There's no static check; it's up to the user-wrapWarnTcS = wrapTcS--failTcS, panicTcS :: SDoc -> TcS a-warnTcS :: WarningFlag -> SDoc -> TcS ()-addErrTcS :: SDoc -> TcS ()-failTcS = wrapTcS . TcM.failWith-warnTcS flag = wrapTcS . TcM.addWarn (Reason flag)-addErrTcS = wrapTcS . TcM.addErr-panicTcS doc = pprPanic "GHC.Tc.Solver.Canonical" doc--traceTcS :: String -> SDoc -> TcS ()-traceTcS herald doc = wrapTcS (TcM.traceTc herald doc)-{-# INLINE traceTcS #-} -- see Note [INLINE conditional tracing utilities]--runTcPluginTcS :: TcPluginM a -> TcS a-runTcPluginTcS m = wrapTcS . runTcPluginM m =<< getTcEvBindsVar--instance HasDynFlags TcS where- getDynFlags = wrapTcS getDynFlags--getGlobalRdrEnvTcS :: TcS GlobalRdrEnv-getGlobalRdrEnvTcS = wrapTcS TcM.getGlobalRdrEnv--bumpStepCountTcS :: TcS ()-bumpStepCountTcS = TcS $ \env -> do { let ref = tcs_count env- ; n <- TcM.readTcRef ref- ; TcM.writeTcRef ref (n+1) }--csTraceTcS :: SDoc -> TcS ()-csTraceTcS doc- = wrapTcS $ csTraceTcM (return doc)-{-# INLINE csTraceTcS #-} -- see Note [INLINE conditional tracing utilities]--traceFireTcS :: CtEvidence -> SDoc -> TcS ()--- Dump a rule-firing trace-traceFireTcS ev doc- = TcS $ \env -> csTraceTcM $- do { n <- TcM.readTcRef (tcs_count env)- ; tclvl <- TcM.getTcLevel- ; return (hang (text "Step" <+> int n- <> brackets (text "l:" <> ppr tclvl <> comma <>- text "d:" <> ppr (ctLocDepth (ctEvLoc ev)))- <+> doc <> colon)- 4 (ppr ev)) }-{-# INLINE traceFireTcS #-} -- see Note [INLINE conditional tracing utilities]--csTraceTcM :: TcM SDoc -> TcM ()--- Constraint-solver tracing, -ddump-cs-trace-csTraceTcM mk_doc- = do { dflags <- getDynFlags- ; when ( dopt Opt_D_dump_cs_trace dflags- || dopt Opt_D_dump_tc_trace dflags )- ( do { msg <- mk_doc- ; TcM.dumpTcRn False- (dumpOptionsFromFlag Opt_D_dump_cs_trace)- "" FormatText- msg }) }-{-# INLINE csTraceTcM #-} -- see Note [INLINE conditional tracing utilities]--runTcS :: TcS a -- What to run- -> TcM (a, EvBindMap)-runTcS tcs- = do { ev_binds_var <- TcM.newTcEvBinds- ; res <- runTcSWithEvBinds ev_binds_var True tcs- ; ev_binds <- TcM.getTcEvBindsMap ev_binds_var- ; return (res, ev_binds) }--- | This variant of 'runTcS' will keep solving, even when only Deriveds--- are left around. It also doesn't return any evidence, as callers won't--- need it.-runTcSDeriveds :: TcS a -> TcM a-runTcSDeriveds tcs- = do { ev_binds_var <- TcM.newTcEvBinds- ; runTcSWithEvBinds ev_binds_var True tcs }---- | This can deal only with equality constraints.-runTcSEqualities :: TcS a -> TcM a-runTcSEqualities thing_inside- = do { ev_binds_var <- TcM.newNoTcEvBinds- ; runTcSWithEvBinds ev_binds_var True thing_inside }---- | A variant of 'runTcS' that takes and returns an 'InertSet' for--- later resumption of the 'TcS' session. Crucially, it doesn't--- 'unflattenGivens' when done.-runTcSInerts :: InertSet -> TcS a -> TcM (a, InertSet)-runTcSInerts inerts tcs = do- ev_binds_var <- TcM.newTcEvBinds- -- Passing False here to prohibit unflattening- runTcSWithEvBinds ev_binds_var False $ do- setTcSInerts inerts- a <- tcs- new_inerts <- getTcSInerts- return (a, new_inerts)--runTcSWithEvBinds :: EvBindsVar- -> Bool -- ^ Unflatten types afterwards? Don't if you want to reuse the InertSet.- -> TcS a- -> TcM a-runTcSWithEvBinds ev_binds_var unflatten tcs- = do { unified_var <- TcM.newTcRef 0- ; step_count <- TcM.newTcRef 0- ; inert_var <- TcM.newTcRef emptyInert- ; wl_var <- TcM.newTcRef emptyWorkList- ; let env = TcSEnv { tcs_ev_binds = ev_binds_var- , tcs_unified = unified_var- , tcs_count = step_count- , tcs_inerts = inert_var- , tcs_worklist = wl_var }-- -- Run the computation- ; res <- unTcS tcs env-- ; count <- TcM.readTcRef step_count- ; when (count > 0) $- csTraceTcM $ return (text "Constraint solver steps =" <+> int count)-- ; when unflatten $ unflattenGivens inert_var--#if defined(DEBUG)- ; ev_binds <- TcM.getTcEvBindsMap ev_binds_var- ; checkForCyclicBinds ev_binds-#endif-- ; return res }-------------------------------#if defined(DEBUG)-checkForCyclicBinds :: EvBindMap -> TcM ()-checkForCyclicBinds ev_binds_map- | null cycles- = return ()- | null coercion_cycles- = TcM.traceTc "Cycle in evidence binds" $ ppr cycles- | otherwise- = pprPanic "Cycle in coercion bindings" $ ppr coercion_cycles- where- ev_binds = evBindMapBinds ev_binds_map-- cycles :: [[EvBind]]- cycles = [c | CyclicSCC c <- stronglyConnCompFromEdgedVerticesUniq edges]-- coercion_cycles = [c | c <- cycles, any is_co_bind c]- is_co_bind (EvBind { eb_lhs = b }) = isEqPrimPred (varType b)-- edges :: [ Node EvVar EvBind ]- edges = [ DigraphNode bind bndr (nonDetEltsUniqSet (evVarsOfTerm rhs))- | bind@(EvBind { eb_lhs = bndr, eb_rhs = rhs}) <- bagToList ev_binds ]- -- It's OK to use nonDetEltsUFM here as- -- stronglyConnCompFromEdgedVertices is still deterministic even- -- if the edges are in nondeterministic order as explained in- -- Note [Deterministic SCC] in GHC.Data.Graph.Directed.-#endif-------------------------------setEvBindsTcS :: EvBindsVar -> TcS a -> TcS a-setEvBindsTcS ref (TcS thing_inside)- = TcS $ \ env -> thing_inside (env { tcs_ev_binds = ref })--nestImplicTcS :: EvBindsVar- -> TcLevel -> TcS a- -> TcS a-nestImplicTcS ref inner_tclvl (TcS thing_inside)- = TcS $ \ TcSEnv { tcs_unified = unified_var- , tcs_inerts = old_inert_var- , tcs_count = count- } ->- do { inerts <- TcM.readTcRef old_inert_var- ; let nest_inert = emptyInert- { inert_cans = inert_cans inerts- , inert_solved_dicts = inert_solved_dicts inerts }- -- See Note [Do not inherit the flat cache]- ; new_inert_var <- TcM.newTcRef nest_inert- ; new_wl_var <- TcM.newTcRef emptyWorkList- ; let nest_env = TcSEnv { tcs_ev_binds = ref- , tcs_unified = unified_var- , tcs_count = count- , tcs_inerts = new_inert_var- , tcs_worklist = new_wl_var }- ; res <- TcM.setTcLevel inner_tclvl $- thing_inside nest_env-- ; unflattenGivens new_inert_var--#if defined(DEBUG)- -- Perform a check that the thing_inside did not cause cycles- ; ev_binds <- TcM.getTcEvBindsMap ref- ; checkForCyclicBinds ev_binds-#endif- ; return res }--{- Note [Do not inherit the flat cache]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We do not want to inherit the flat cache when processing nested-implications. Consider- a ~ F b, forall c. b~Int => blah-If we have F b ~ fsk in the flat-cache, and we push that into the-nested implication, we might miss that F b can be rewritten to F Int,-and hence perhaps solve it. Moreover, the fsk from outside is-flattened out after solving the outer level, but and we don't-do that flattening recursively.--}--nestTcS :: TcS a -> TcS a--- Use the current untouchables, augmenting the current--- evidence bindings, and solved dictionaries--- But have no effect on the InertCans, or on the inert_flat_cache--- (we want to inherit the latter from processing the Givens)-nestTcS (TcS thing_inside)- = TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var }) ->- do { inerts <- TcM.readTcRef inerts_var- ; new_inert_var <- TcM.newTcRef inerts- ; new_wl_var <- TcM.newTcRef emptyWorkList- ; let nest_env = env { tcs_inerts = new_inert_var- , tcs_worklist = new_wl_var }-- ; res <- thing_inside nest_env-- ; new_inerts <- TcM.readTcRef new_inert_var-- -- we want to propagate the safe haskell failures- ; let old_ic = inert_cans inerts- new_ic = inert_cans new_inerts- nxt_ic = old_ic { inert_safehask = inert_safehask new_ic }-- ; TcM.writeTcRef inerts_var -- See Note [Propagate the solved dictionaries]- (inerts { inert_solved_dicts = inert_solved_dicts new_inerts- , inert_cans = nxt_ic })-- ; return res }--emitImplicationTcS :: TcLevel -> SkolemInfo- -> [TcTyVar] -- Skolems- -> [EvVar] -- Givens- -> Cts -- Wanteds- -> TcS TcEvBinds--- Add an implication to the TcS monad work-list-emitImplicationTcS new_tclvl skol_info skol_tvs givens wanteds- = do { let wc = emptyWC { wc_simple = wanteds }- ; imp <- wrapTcS $- do { ev_binds_var <- TcM.newTcEvBinds- ; imp <- TcM.newImplication- ; return (imp { ic_tclvl = new_tclvl- , ic_skols = skol_tvs- , ic_given = givens- , ic_wanted = wc- , ic_binds = ev_binds_var- , ic_info = skol_info }) }-- ; emitImplication imp- ; return (TcEvBinds (ic_binds imp)) }--emitTvImplicationTcS :: TcLevel -> SkolemInfo- -> [TcTyVar] -- Skolems- -> Cts -- Wanteds- -> TcS ()--- Just like emitImplicationTcS but no givens and no bindings-emitTvImplicationTcS new_tclvl skol_info skol_tvs wanteds- = do { let wc = emptyWC { wc_simple = wanteds }- ; imp <- wrapTcS $- do { ev_binds_var <- TcM.newNoTcEvBinds- ; imp <- TcM.newImplication- ; return (imp { ic_tclvl = new_tclvl- , ic_skols = skol_tvs- , ic_wanted = wc- , ic_binds = ev_binds_var- , ic_info = skol_info }) }-- ; emitImplication imp }---{- Note [Propagate the solved dictionaries]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-It's really quite important that nestTcS does not discard the solved-dictionaries from the thing_inside.-Consider- Eq [a]- forall b. empty => Eq [a]-We solve the simple (Eq [a]), under nestTcS, and then turn our attention to-the implications. It's definitely fine to use the solved dictionaries on-the inner implications, and it can make a significant performance difference-if you do so.--}---- Getters and setters of GHC.Tc.Utils.Env fields--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~---- Getter of inerts and worklist-getTcSInertsRef :: TcS (IORef InertSet)-getTcSInertsRef = TcS (return . tcs_inerts)--getTcSWorkListRef :: TcS (IORef WorkList)-getTcSWorkListRef = TcS (return . tcs_worklist)--getTcSInerts :: TcS InertSet-getTcSInerts = getTcSInertsRef >>= readTcRef--setTcSInerts :: InertSet -> TcS ()-setTcSInerts ics = do { r <- getTcSInertsRef; writeTcRef r ics }--getWorkListImplics :: TcS (Bag Implication)-getWorkListImplics- = do { wl_var <- getTcSWorkListRef- ; wl_curr <- readTcRef wl_var- ; return (wl_implics wl_curr) }--pushLevelNoWorkList :: SDoc -> TcS a -> TcS (TcLevel, a)--- Push the level and run thing_inside--- However, thing_inside should not generate any work items-#if defined(DEBUG)-pushLevelNoWorkList err_doc (TcS thing_inside)- = TcS (\env -> TcM.pushTcLevelM $- thing_inside (env { tcs_worklist = wl_panic })- )- where- wl_panic = pprPanic "GHC.Tc.Solver.Monad.buildImplication" err_doc- -- This panic checks that the thing-inside- -- does not emit any work-list constraints-#else-pushLevelNoWorkList _ (TcS thing_inside)- = TcS (\env -> TcM.pushTcLevelM (thing_inside env)) -- Don't check-#endif--updWorkListTcS :: (WorkList -> WorkList) -> TcS ()-updWorkListTcS f- = do { wl_var <- getTcSWorkListRef- ; updTcRef wl_var f }--emitWorkNC :: [CtEvidence] -> TcS ()-emitWorkNC evs- | null evs- = return ()- | otherwise- = emitWork (map mkNonCanonical evs)--emitWork :: [Ct] -> TcS ()-emitWork [] = return () -- avoid printing, among other work-emitWork cts- = do { traceTcS "Emitting fresh work" (vcat (map ppr cts))- ; updWorkListTcS (extendWorkListCts cts) }--emitImplication :: Implication -> TcS ()-emitImplication implic- = updWorkListTcS (extendWorkListImplic implic)--newTcRef :: a -> TcS (TcRef a)-newTcRef x = wrapTcS (TcM.newTcRef x)--readTcRef :: TcRef a -> TcS a-readTcRef ref = wrapTcS (TcM.readTcRef ref)--writeTcRef :: TcRef a -> a -> TcS ()-writeTcRef ref val = wrapTcS (TcM.writeTcRef ref val)--updTcRef :: TcRef a -> (a->a) -> TcS ()-updTcRef ref upd_fn = wrapTcS (TcM.updTcRef ref upd_fn)--getTcEvBindsVar :: TcS EvBindsVar-getTcEvBindsVar = TcS (return . tcs_ev_binds)--getTcLevel :: TcS TcLevel-getTcLevel = wrapTcS TcM.getTcLevel--getTcEvTyCoVars :: EvBindsVar -> TcS TyCoVarSet-getTcEvTyCoVars ev_binds_var- = wrapTcS $ TcM.getTcEvTyCoVars ev_binds_var--getTcEvBindsMap :: EvBindsVar -> TcS EvBindMap-getTcEvBindsMap ev_binds_var- = wrapTcS $ TcM.getTcEvBindsMap ev_binds_var--setTcEvBindsMap :: EvBindsVar -> EvBindMap -> TcS ()-setTcEvBindsMap ev_binds_var binds- = wrapTcS $ TcM.setTcEvBindsMap ev_binds_var binds--unifyTyVar :: TcTyVar -> TcType -> TcS ()--- Unify a meta-tyvar with a type--- We keep track of how many unifications have happened in tcs_unified,------ We should never unify the same variable twice!-unifyTyVar tv ty- = ASSERT2( isMetaTyVar tv, ppr tv )- TcS $ \ env ->- do { TcM.traceTc "unifyTyVar" (ppr tv <+> text ":=" <+> ppr ty)- ; TcM.writeMetaTyVar tv ty- ; TcM.updTcRef (tcs_unified env) (+1) }--reportUnifications :: TcS a -> TcS (Int, a)-reportUnifications (TcS thing_inside)- = TcS $ \ env ->- do { inner_unified <- TcM.newTcRef 0- ; res <- thing_inside (env { tcs_unified = inner_unified })- ; n_unifs <- TcM.readTcRef inner_unified- ; TcM.updTcRef (tcs_unified env) (+ n_unifs)- ; return (n_unifs, res) }--getDefaultInfo :: TcS ([Type], (Bool, Bool))-getDefaultInfo = wrapTcS TcM.tcGetDefaultTys---- Just get some environments needed for instance looking up and matching--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--getInstEnvs :: TcS InstEnvs-getInstEnvs = wrapTcS $ TcM.tcGetInstEnvs--getFamInstEnvs :: TcS (FamInstEnv, FamInstEnv)-getFamInstEnvs = wrapTcS $ FamInst.tcGetFamInstEnvs--getTopEnv :: TcS HscEnv-getTopEnv = wrapTcS $ TcM.getTopEnv--getGblEnv :: TcS TcGblEnv-getGblEnv = wrapTcS $ TcM.getGblEnv--getLclEnv :: TcS TcLclEnv-getLclEnv = wrapTcS $ TcM.getLclEnv--tcLookupClass :: Name -> TcS Class-tcLookupClass c = wrapTcS $ TcM.tcLookupClass c--tcLookupId :: Name -> TcS Id-tcLookupId n = wrapTcS $ TcM.tcLookupId n---- Setting names as used (used in the deriving of Coercible evidence)--- Too hackish to expose it to TcS? In that case somehow extract the used--- constructors from the result of solveInteract-addUsedGREs :: [GlobalRdrElt] -> TcS ()-addUsedGREs gres = wrapTcS $ TcM.addUsedGREs gres--addUsedGRE :: Bool -> GlobalRdrElt -> TcS ()-addUsedGRE warn_if_deprec gre = wrapTcS $ TcM.addUsedGRE warn_if_deprec gre--keepAlive :: Name -> TcS ()-keepAlive = wrapTcS . TcM.keepAlive---- Various smaller utilities [TODO, maybe will be absorbed in the instance matcher]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--checkWellStagedDFun :: CtLoc -> InstanceWhat -> PredType -> TcS ()--- Check that we do not try to use an instance before it is available. E.g.--- instance Eq T where ...--- f x = $( ... (\(p::T) -> p == p)... )--- Here we can't use the equality function from the instance in the splice--checkWellStagedDFun loc what pred- | TopLevInstance { iw_dfun_id = dfun_id } <- what- , let bind_lvl = TcM.topIdLvl dfun_id- , bind_lvl > impLevel- = wrapTcS $ TcM.setCtLocM loc $- do { use_stage <- TcM.getStage- ; TcM.checkWellStaged pp_thing bind_lvl (thLevel use_stage) }-- | otherwise- = return () -- Fast path for common case- where- pp_thing = text "instance for" <+> quotes (ppr pred)--pprEq :: TcType -> TcType -> SDoc-pprEq ty1 ty2 = pprParendType ty1 <+> char '~' <+> pprParendType ty2--isFilledMetaTyVar_maybe :: TcTyVar -> TcS (Maybe Type)-isFilledMetaTyVar_maybe tv = wrapTcS (TcM.isFilledMetaTyVar_maybe tv)--isFilledMetaTyVar :: TcTyVar -> TcS Bool-isFilledMetaTyVar tv = wrapTcS (TcM.isFilledMetaTyVar tv)--zonkTyCoVarsAndFV :: TcTyCoVarSet -> TcS TcTyCoVarSet-zonkTyCoVarsAndFV tvs = wrapTcS (TcM.zonkTyCoVarsAndFV tvs)--zonkTyCoVarsAndFVList :: [TcTyCoVar] -> TcS [TcTyCoVar]-zonkTyCoVarsAndFVList tvs = wrapTcS (TcM.zonkTyCoVarsAndFVList tvs)--zonkCo :: Coercion -> TcS Coercion-zonkCo = wrapTcS . TcM.zonkCo--zonkTcType :: TcType -> TcS TcType-zonkTcType ty = wrapTcS (TcM.zonkTcType ty)--zonkTcTypes :: [TcType] -> TcS [TcType]-zonkTcTypes tys = wrapTcS (TcM.zonkTcTypes tys)--zonkTcTyVar :: TcTyVar -> TcS TcType-zonkTcTyVar tv = wrapTcS (TcM.zonkTcTyVar tv)--zonkSimples :: Cts -> TcS Cts-zonkSimples cts = wrapTcS (TcM.zonkSimples cts)--zonkWC :: WantedConstraints -> TcS WantedConstraints-zonkWC wc = wrapTcS (TcM.zonkWC wc)--zonkTyCoVarKind :: TcTyCoVar -> TcS TcTyCoVar-zonkTyCoVarKind tv = wrapTcS (TcM.zonkTyCoVarKind tv)--{- *********************************************************************-* *-* Flatten skolems *-* *-********************************************************************* -}--newFlattenSkolem :: CtFlavour -> CtLoc- -> TyCon -> [TcType] -- F xis- -> TcS (CtEvidence, Coercion, TcTyVar) -- [G/WD] x:: F xis ~ fsk-newFlattenSkolem flav loc tc xis- = do { stuff@(ev, co, fsk) <- new_skolem- ; let fsk_ty = mkTyVarTy fsk- ; extendFlatCache tc xis (co, fsk_ty, ctEvFlavour ev)- ; return stuff }- where- fam_ty = mkTyConApp tc xis-- new_skolem- | Given <- flav- = do { fsk <- wrapTcS (TcM.newFskTyVar fam_ty)-- -- Extend the inert_fsks list, for use by unflattenGivens- ; updInertTcS $ \is -> is { inert_fsks = (fsk, fam_ty) : inert_fsks is }-- -- Construct the Refl evidence- ; let pred = mkPrimEqPred fam_ty (mkTyVarTy fsk)- co = mkNomReflCo fam_ty- ; ev <- newGivenEvVar loc (pred, evCoercion co)- ; return (ev, co, fsk) }-- | otherwise -- Generate a [WD] for both Wanted and Derived- -- See Note [No Derived CFunEqCans]- = do { fmv <- wrapTcS (TcM.newFmvTyVar fam_ty)- -- See (2a) in "GHC.Tc.Solver.Canonical"- -- Note [Equalities with incompatible kinds]- ; (ev, hole_co) <- newWantedEq_SI NoBlockSubst WDeriv loc Nominal- fam_ty (mkTyVarTy fmv)- ; return (ev, hole_co, fmv) }-------------------------------unflattenGivens :: IORef InertSet -> TcM ()--- Unflatten all the fsks created by flattening types in Given--- constraints. We must be sure to do this, else we end up with--- flatten-skolems buried in any residual Wanteds------ NB: this is the /only/ way that a fsk (MetaDetails = FlatSkolTv)--- is filled in. Nothing else does so.------ It's here (rather than in GHC.Tc.Solver.Flatten) because the Right Places--- to call it are in runTcSWithEvBinds/nestImplicTcS, where it--- is nicely paired with the creation an empty inert_fsks list.-unflattenGivens inert_var- = do { inerts <- TcM.readTcRef inert_var- ; TcM.traceTc "unflattenGivens" (ppr (inert_fsks inerts))- ; mapM_ flatten_one (inert_fsks inerts) }- where- flatten_one (fsk, ty) = TcM.writeMetaTyVar fsk ty-------------------------------extendFlatCache :: TyCon -> [Type] -> (TcCoercion, TcType, CtFlavour) -> TcS ()-extendFlatCache tc xi_args stuff@(_, ty, fl)- | isGivenOrWDeriv fl -- Maintain the invariant that inert_flat_cache- -- only has [G] and [WD] CFunEqCans- = do { dflags <- getDynFlags- ; when (gopt Opt_FlatCache dflags) $- do { traceTcS "extendFlatCache" (vcat [ ppr tc <+> ppr xi_args- , ppr fl, ppr ty ])- -- 'co' can be bottom, in the case of derived items- ; updInertTcS $ \ is@(IS { inert_flat_cache = fc }) ->- is { inert_flat_cache = insertExactFunEq fc tc xi_args stuff } } }-- | otherwise- = return ()-------------------------------unflattenFmv :: TcTyVar -> TcType -> TcS ()--- Fill a flatten-meta-var, simply by unifying it.--- This does NOT count as a unification in tcs_unified.-unflattenFmv tv ty- = ASSERT2( isMetaTyVar tv, ppr tv )- TcS $ \ _ ->- do { TcM.traceTc "unflattenFmv" (ppr tv <+> text ":=" <+> ppr ty)- ; TcM.writeMetaTyVar tv ty }-------------------------------demoteUnfilledFmv :: TcTyVar -> TcS ()--- If a flatten-meta-var is still un-filled,--- turn it into an ordinary meta-var-demoteUnfilledFmv fmv- = wrapTcS $ do { is_filled <- TcM.isFilledMetaTyVar fmv- ; unless is_filled $- do { tv_ty <- TcM.newFlexiTyVarTy (tyVarKind fmv)- ; TcM.writeMetaTyVar fmv tv_ty } }--------------------------------dischargeFunEq :: CtEvidence -> TcTyVar -> TcCoercion -> TcType -> TcS ()--- (dischargeFunEq tv co ty)--- Preconditions--- - ev :: F tys ~ tv is a CFunEqCan--- - tv is a FlatMetaTv of FlatSkolTv--- - co :: F tys ~ xi--- - fmv/fsk `notElem` xi--- - fmv not filled (for Wanteds)--- - xi is flattened (and obeys Note [Almost function-free] in GHC.Tc.Types)------ Then for [W] or [WD], we actually fill in the fmv:--- set fmv := xi,--- set ev := co--- kick out any inert things that are now rewritable------ For [D], we instead emit an equality that must ultimately hold--- [D] xi ~ fmv--- Does not evaluate 'co' if 'ev' is Derived------ For [G], emit this equality--- [G] (sym ev; co) :: fsk ~ xi---- See GHC.Tc.Solver.Flatten Note [The flattening story],--- especially "Ownership of fsk/fmv"-dischargeFunEq (CtGiven { ctev_evar = old_evar, ctev_loc = loc }) fsk co xi- = do { new_ev <- newGivenEvVar loc ( new_pred, evCoercion new_co )- ; emitWorkNC [new_ev] }- where- new_pred = mkPrimEqPred (mkTyVarTy fsk) xi- new_co = mkTcSymCo (mkTcCoVarCo old_evar) `mkTcTransCo` co--dischargeFunEq ev@(CtWanted { ctev_dest = dest }) fmv co xi- = ASSERT2( not (fmv `elemVarSet` tyCoVarsOfType xi), ppr ev $$ ppr fmv $$ ppr xi )- do { setWantedEvTerm dest (evCoercion co)- ; unflattenFmv fmv xi- ; n_kicked <- kickOutAfterUnification fmv- ; traceTcS "dischargeFmv" (ppr fmv <+> equals <+> ppr xi $$ pprKicked n_kicked) }--dischargeFunEq (CtDerived { ctev_loc = loc }) fmv _co xi- = emitNewDerivedEq loc Nominal xi (mkTyVarTy fmv)- -- FunEqs are always at Nominal role--pprKicked :: Int -> SDoc-pprKicked 0 = empty-pprKicked n = parens (int n <+> text "kicked out")--{- *********************************************************************-* *-* Instantiation etc.-* *-********************************************************************* -}---- Instantiations--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--instDFunType :: DFunId -> [DFunInstType] -> TcS ([TcType], TcThetaType)-instDFunType dfun_id inst_tys- = wrapTcS $ TcM.instDFunType dfun_id inst_tys--newFlexiTcSTy :: Kind -> TcS TcType-newFlexiTcSTy knd = wrapTcS (TcM.newFlexiTyVarTy knd)--cloneMetaTyVar :: TcTyVar -> TcS TcTyVar-cloneMetaTyVar tv = wrapTcS (TcM.cloneMetaTyVar tv)--instFlexi :: [TKVar] -> TcS TCvSubst-instFlexi = instFlexiX emptyTCvSubst--instFlexiX :: TCvSubst -> [TKVar] -> TcS TCvSubst-instFlexiX subst tvs- = wrapTcS (foldlM instFlexiHelper subst tvs)--instFlexiHelper :: TCvSubst -> TKVar -> TcM TCvSubst-instFlexiHelper subst tv- = do { uniq <- TcM.newUnique- ; details <- TcM.newMetaDetails TauTv- ; let name = setNameUnique (tyVarName tv) uniq- kind = substTyUnchecked subst (tyVarKind tv)- ty' = mkTyVarTy (mkTcTyVar name kind details)- ; TcM.traceTc "instFlexi" (ppr ty')- ; return (extendTvSubst subst tv ty') }--matchGlobalInst :: DynFlags- -> Bool -- True <=> caller is the short-cut solver- -- See Note [Shortcut solving: overlap]- -> Class -> [Type] -> TcS TcM.ClsInstResult-matchGlobalInst dflags short_cut cls tys- = wrapTcS (TcM.matchGlobalInst dflags short_cut cls tys)--tcInstSkolTyVarsX :: TCvSubst -> [TyVar] -> TcS (TCvSubst, [TcTyVar])-tcInstSkolTyVarsX subst tvs = wrapTcS $ TcM.tcInstSkolTyVarsX subst tvs---- Creating and setting evidence variables and CtFlavors--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--data MaybeNew = Fresh CtEvidence | Cached EvExpr--isFresh :: MaybeNew -> Bool-isFresh (Fresh {}) = True-isFresh (Cached {}) = False--freshGoals :: [MaybeNew] -> [CtEvidence]-freshGoals mns = [ ctev | Fresh ctev <- mns ]--getEvExpr :: MaybeNew -> EvExpr-getEvExpr (Fresh ctev) = ctEvExpr ctev-getEvExpr (Cached evt) = evt--setEvBind :: EvBind -> TcS ()-setEvBind ev_bind- = do { evb <- getTcEvBindsVar- ; wrapTcS $ TcM.addTcEvBind evb ev_bind }---- | Mark variables as used filling a coercion hole-useVars :: CoVarSet -> TcS ()-useVars co_vars- = do { ev_binds_var <- getTcEvBindsVar- ; let ref = ebv_tcvs ev_binds_var- ; wrapTcS $- do { tcvs <- TcM.readTcRef ref- ; let tcvs' = tcvs `unionVarSet` co_vars- ; TcM.writeTcRef ref tcvs' } }---- | Equalities only-setWantedEq :: TcEvDest -> Coercion -> TcS ()-setWantedEq (HoleDest hole) co- = do { useVars (coVarsOfCo co)- ; fillCoercionHole hole co }-setWantedEq (EvVarDest ev) _ = pprPanic "setWantedEq" (ppr ev)---- | Good for both equalities and non-equalities-setWantedEvTerm :: TcEvDest -> EvTerm -> TcS ()-setWantedEvTerm (HoleDest hole) tm- | Just co <- evTermCoercion_maybe tm- = do { useVars (coVarsOfCo co)- ; fillCoercionHole hole co }- | otherwise- = -- See Note [Yukky eq_sel for a HoleDest]- do { let co_var = coHoleCoVar hole- ; setEvBind (mkWantedEvBind co_var tm)- ; fillCoercionHole hole (mkTcCoVarCo co_var) }--setWantedEvTerm (EvVarDest ev_id) tm- = setEvBind (mkWantedEvBind ev_id tm)--{- Note [Yukky eq_sel for a HoleDest]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-How can it be that a Wanted with HoleDest gets evidence that isn't-just a coercion? i.e. evTermCoercion_maybe returns Nothing.--Consider [G] forall a. blah => a ~ T- [W] S ~# T--Then doTopReactEqPred carefully looks up the (boxed) constraint (S ~-T) in the quantified constraints, and wraps the (boxed) evidence it-gets back in an eq_sel to extract the unboxed (S ~# T). We can't put-that term into a coercion, so we add a value binding- h = eq_sel (...)-and the coercion variable h to fill the coercion hole.-We even re-use the CoHole's Id for this binding!--Yuk!--}--fillCoercionHole :: CoercionHole -> Coercion -> TcS ()-fillCoercionHole hole co- = do { wrapTcS $ TcM.fillCoercionHole hole co- ; kickOutAfterFillingCoercionHole hole }--setEvBindIfWanted :: CtEvidence -> EvTerm -> TcS ()-setEvBindIfWanted ev tm- = case ev of- CtWanted { ctev_dest = dest } -> setWantedEvTerm dest tm- _ -> return ()--newTcEvBinds :: TcS EvBindsVar-newTcEvBinds = wrapTcS TcM.newTcEvBinds--newNoTcEvBinds :: TcS EvBindsVar-newNoTcEvBinds = wrapTcS TcM.newNoTcEvBinds--newEvVar :: TcPredType -> TcS EvVar-newEvVar pred = wrapTcS (TcM.newEvVar pred)--newGivenEvVar :: CtLoc -> (TcPredType, EvTerm) -> TcS CtEvidence--- Make a new variable of the given PredType,--- immediately bind it to the given term--- and return its CtEvidence--- See Note [Bind new Givens immediately] in GHC.Tc.Types.Constraint-newGivenEvVar loc (pred, rhs)- = do { new_ev <- newBoundEvVarId pred rhs- ; return (CtGiven { ctev_pred = pred, ctev_evar = new_ev, ctev_loc = loc }) }---- | Make a new 'Id' of the given type, bound (in the monad's EvBinds) to the--- given term-newBoundEvVarId :: TcPredType -> EvTerm -> TcS EvVar-newBoundEvVarId pred rhs- = do { new_ev <- newEvVar pred- ; setEvBind (mkGivenEvBind new_ev rhs)- ; return new_ev }--newGivenEvVars :: CtLoc -> [(TcPredType, EvTerm)] -> TcS [CtEvidence]-newGivenEvVars loc pts = mapM (newGivenEvVar loc) pts--emitNewWantedEq :: CtLoc -> Role -> TcType -> TcType -> TcS Coercion--- | Emit a new Wanted equality into the work-list-emitNewWantedEq loc role ty1 ty2- = do { (ev, co) <- newWantedEq loc role ty1 ty2- ; updWorkListTcS (extendWorkListEq (mkNonCanonical ev))- ; return co }---- | Make a new equality CtEvidence-newWantedEq :: CtLoc -> Role -> TcType -> TcType- -> TcS (CtEvidence, Coercion)-newWantedEq = newWantedEq_SI YesBlockSubst WDeriv--newWantedEq_SI :: BlockSubstFlag -> ShadowInfo -> CtLoc -> Role- -> TcType -> TcType- -> TcS (CtEvidence, Coercion)-newWantedEq_SI blocker si loc role ty1 ty2- = do { hole <- wrapTcS $ TcM.newCoercionHole blocker pty- ; traceTcS "Emitting new coercion hole" (ppr hole <+> dcolon <+> ppr pty)- ; return ( CtWanted { ctev_pred = pty, ctev_dest = HoleDest hole- , ctev_nosh = si- , ctev_loc = loc}- , mkHoleCo hole ) }- where- pty = mkPrimEqPredRole role ty1 ty2---- no equalities here. Use newWantedEq instead-newWantedEvVarNC :: CtLoc -> TcPredType -> TcS CtEvidence-newWantedEvVarNC = newWantedEvVarNC_SI WDeriv--newWantedEvVarNC_SI :: ShadowInfo -> CtLoc -> TcPredType -> TcS CtEvidence--- Don't look up in the solved/inerts; we know it's not there-newWantedEvVarNC_SI si loc pty- = do { new_ev <- newEvVar pty- ; traceTcS "Emitting new wanted" (ppr new_ev <+> dcolon <+> ppr pty $$- pprCtLoc loc)- ; return (CtWanted { ctev_pred = pty, ctev_dest = EvVarDest new_ev- , ctev_nosh = si- , ctev_loc = loc })}--newWantedEvVar :: CtLoc -> TcPredType -> TcS MaybeNew-newWantedEvVar = newWantedEvVar_SI WDeriv--newWantedEvVar_SI :: ShadowInfo -> CtLoc -> TcPredType -> TcS MaybeNew--- For anything except ClassPred, this is the same as newWantedEvVarNC-newWantedEvVar_SI si loc pty- = do { mb_ct <- lookupInInerts loc pty- ; case mb_ct of- Just ctev- | not (isDerived ctev)- -> do { traceTcS "newWantedEvVar/cache hit" $ ppr ctev- ; return $ Cached (ctEvExpr ctev) }- _ -> do { ctev <- newWantedEvVarNC_SI si loc pty- ; return (Fresh ctev) } }--newWanted :: CtLoc -> PredType -> TcS MaybeNew--- Deals with both equalities and non equalities. Tries to look--- up non-equalities in the cache-newWanted = newWanted_SI WDeriv--newWanted_SI :: ShadowInfo -> CtLoc -> PredType -> TcS MaybeNew-newWanted_SI si loc pty- | Just (role, ty1, ty2) <- getEqPredTys_maybe pty- = Fresh . fst <$> newWantedEq_SI YesBlockSubst si loc role ty1 ty2- | otherwise- = newWantedEvVar_SI si loc pty---- deals with both equalities and non equalities. Doesn't do any cache lookups.-newWantedNC :: CtLoc -> PredType -> TcS CtEvidence-newWantedNC loc pty- | Just (role, ty1, ty2) <- getEqPredTys_maybe pty- = fst <$> newWantedEq loc role ty1 ty2- | otherwise- = newWantedEvVarNC loc pty--emitNewDeriveds :: CtLoc -> [TcPredType] -> TcS ()-emitNewDeriveds loc preds- | null preds- = return ()- | otherwise- = do { evs <- mapM (newDerivedNC loc) preds- ; traceTcS "Emitting new deriveds" (ppr evs)- ; updWorkListTcS (extendWorkListDeriveds evs) }--emitNewDerivedEq :: CtLoc -> Role -> TcType -> TcType -> TcS ()--- Create new equality Derived and put it in the work list--- There's no caching, no lookupInInerts-emitNewDerivedEq loc role ty1 ty2- = do { ev <- newDerivedNC loc (mkPrimEqPredRole role ty1 ty2)- ; traceTcS "Emitting new derived equality" (ppr ev $$ pprCtLoc loc)- ; updWorkListTcS (extendWorkListEq (mkNonCanonical ev)) }- -- Very important: put in the wl_eqs- -- See Note [Prioritise equalities] (Avoiding fundep iteration)--newDerivedNC :: CtLoc -> TcPredType -> TcS CtEvidence-newDerivedNC loc pred- = return $ CtDerived { ctev_pred = pred, ctev_loc = loc }---- --------- Check done in GHC.Tc.Solver.Interact.selectNewWorkItem???? ------------ | Checks if the depth of the given location is too much. Fails if--- it's too big, with an appropriate error message.-checkReductionDepth :: CtLoc -> TcType -- ^ type being reduced- -> TcS ()-checkReductionDepth loc ty- = do { dflags <- getDynFlags- ; when (subGoalDepthExceeded dflags (ctLocDepth loc)) $- wrapErrTcS $- solverDepthErrorTcS loc ty }--matchFam :: TyCon -> [Type] -> TcS (Maybe (CoercionN, TcType))--- Given (F tys) return (ty, co), where co :: F tys ~N ty-matchFam tycon args = wrapTcS $ matchFamTcM tycon args--matchFamTcM :: TyCon -> [Type] -> TcM (Maybe (CoercionN, TcType))--- Given (F tys) return (ty, co), where co :: F tys ~N ty-matchFamTcM tycon args- = do { fam_envs <- FamInst.tcGetFamInstEnvs- ; let match_fam_result- = reduceTyFamApp_maybe fam_envs Nominal tycon args- ; TcM.traceTc "matchFamTcM" $- vcat [ text "Matching:" <+> ppr (mkTyConApp tycon args)- , ppr_res match_fam_result ]- ; return match_fam_result }- where- ppr_res Nothing = text "Match failed"- ppr_res (Just (co,ty)) = hang (text "Match succeeded:")- 2 (vcat [ text "Rewrites to:" <+> ppr ty- , text "Coercion:" <+> ppr co ])--{--Note [Residual implications]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The wl_implics in the WorkList are the residual implication-constraints that are generated while solving or canonicalising the-current worklist. Specifically, when canonicalising- (forall a. t1 ~ forall a. t2)-from which we get the implication- (forall a. t1 ~ t2)-See GHC.Tc.Solver.Monad.deferTcSForAllEq--}+{-# LANGUAGE CPP, DeriveFunctor, TypeFamilies, ScopedTypeVariables, TypeApplications,+ DerivingStrategies, GeneralizedNewtypeDeriving #-}++{-# OPTIONS_GHC -Wno-incomplete-record-updates -Wno-incomplete-uni-patterns #-}++-- | Type definitions for the constraint solver+module GHC.Tc.Solver.Monad (++ -- The work list+ WorkList(..), isEmptyWorkList, emptyWorkList,+ extendWorkListNonEq, extendWorkListCt,+ extendWorkListCts, extendWorkListEq,+ appendWorkList,+ selectNextWorkItem,+ workListSize,+ getWorkList, updWorkListTcS, pushLevelNoWorkList,++ -- The TcS monad+ TcS, runTcS, runTcSDeriveds, runTcSWithEvBinds, runTcSInerts,+ failTcS, warnTcS, addErrTcS, wrapTcS,+ runTcSEqualities,+ nestTcS, nestImplicTcS, setEvBindsTcS,+ emitImplicationTcS, emitTvImplicationTcS,++ runTcPluginTcS, addUsedGRE, addUsedGREs, keepAlive,+ matchGlobalInst, TcM.ClsInstResult(..),++ QCInst(..),++ -- Tracing etc+ panicTcS, traceTcS,+ traceFireTcS, bumpStepCountTcS, csTraceTcS,+ wrapErrTcS, wrapWarnTcS,+ resetUnificationFlag, setUnificationFlag,++ -- Evidence creation and transformation+ MaybeNew(..), freshGoals, isFresh, getEvExpr,++ newTcEvBinds, newNoTcEvBinds,+ newWantedEq, newWantedEq_SI, emitNewWantedEq,+ newWanted, newWanted_SI, newWantedEvVar,+ newWantedNC, newWantedEvVarNC,+ newDerivedNC,+ newBoundEvVarId,+ unifyTyVar, reportUnifications,+ setEvBind, setWantedEq,+ setWantedEvTerm, setEvBindIfWanted,+ newEvVar, newGivenEvVar, newGivenEvVars,+ emitNewDeriveds, emitNewDerivedEq,+ checkReductionDepth,+ getSolvedDicts, setSolvedDicts,++ getInstEnvs, getFamInstEnvs, -- Getting the environments+ getTopEnv, getGblEnv, getLclEnv,+ getTcEvBindsVar, getTcLevel,+ getTcEvTyCoVars, getTcEvBindsMap, setTcEvBindsMap,+ tcLookupClass, tcLookupId,++ -- Inerts+ InertSet(..), InertCans(..), emptyInert,+ updInertTcS, updInertCans, updInertDicts, updInertIrreds,+ getHasGivenEqs, setInertCans,+ getInertEqs, getInertCans, getInertGivens,+ getInertInsols, getInnermostGivenEqLevel,+ getTcSInerts, setTcSInerts,+ matchableGivens, prohibitedSuperClassSolve, mightMatchLater,+ getUnsolvedInerts,+ removeInertCts, getPendingGivenScs,+ addInertCan, insertFunEq, addInertForAll,+ emitWorkNC, emitWork,+ isImprovable,++ -- The Model+ kickOutAfterUnification,++ -- Inert Safe Haskell safe-overlap failures+ addInertSafehask, insertSafeOverlapFailureTcS, updInertSafehask,+ getSafeOverlapFailures,++ -- Inert CDictCans+ DictMap, emptyDictMap, lookupInertDict, findDictsByClass, addDict,+ addDictsByClass, delDict, foldDicts, filterDicts, findDict,++ -- Inert CEqCans+ EqualCtList(..), findTyEqs, foldTyEqs,+ findEq,++ -- Inert solved dictionaries+ addSolvedDict, lookupSolvedDict,++ -- Irreds+ foldIrreds,++ -- The family application cache+ lookupFamAppInert, lookupFamAppCache, extendFamAppCache,+ pprKicked,++ -- Inert function equalities+ findFunEq, findFunEqsByTyCon,++ instDFunType, -- Instantiation++ -- MetaTyVars+ newFlexiTcSTy, instFlexi, instFlexiX,+ cloneMetaTyVar,+ tcInstSkolTyVarsX,++ TcLevel,+ isFilledMetaTyVar_maybe, isFilledMetaTyVar,+ zonkTyCoVarsAndFV, zonkTcType, zonkTcTypes, zonkTcTyVar, zonkCo,+ zonkTyCoVarsAndFVList,+ zonkSimples, zonkWC,+ zonkTyCoVarKind,++ -- References+ newTcRef, readTcRef, writeTcRef, updTcRef,++ -- Misc+ getDefaultInfo, getDynFlags, getGlobalRdrEnvTcS,+ matchFam, matchFamTcM,+ checkWellStagedDFun,+ pprEq, -- Smaller utils, re-exported from TcM+ -- TODO (DV): these are only really used in the+ -- instance matcher in GHC.Tc.Solver. I am wondering+ -- if the whole instance matcher simply belongs+ -- here++ breakTyVarCycle, rewriterView+) where++#include "GhclibHsVersions.h"++import GHC.Prelude++import GHC.Driver.Env++import qualified GHC.Tc.Utils.Instantiate as TcM+import GHC.Core.InstEnv+import GHC.Tc.Instance.Family as FamInst+import GHC.Core.FamInstEnv++import qualified GHC.Tc.Utils.Monad as TcM+import qualified GHC.Tc.Utils.TcMType as TcM+import qualified GHC.Tc.Instance.Class as TcM( matchGlobalInst, ClsInstResult(..) )+import qualified GHC.Tc.Utils.Env as TcM+ ( checkWellStaged, tcGetDefaultTys, tcLookupClass, tcLookupId, topIdLvl )+import GHC.Tc.Instance.Class( InstanceWhat(..), safeOverlap, instanceReturnsDictCon )+import GHC.Tc.Utils.TcType+import GHC.Driver.Session+import GHC.Core.Type+import qualified GHC.Core.TyCo.Rep as Rep -- this needs to be used only very locally+import GHC.Core.Coercion+import GHC.Core.Unify++import GHC.Utils.Error+import GHC.Tc.Types.Evidence+import GHC.Core.Class+import GHC.Core.TyCon+import GHC.Tc.Errors ( solverDepthErrorTcS )++import GHC.Types.Name+import GHC.Types.TyThing+import GHC.Unit.Module ( HasModule, getModule )+import GHC.Types.Name.Reader ( GlobalRdrEnv, GlobalRdrElt )+import qualified GHC.Rename.Env as TcM+import GHC.Types.Var+import GHC.Types.Var.Env+import GHC.Types.Var.Set+import GHC.Utils.Outputable+import GHC.Utils.Panic+import GHC.Data.Bag as Bag+import GHC.Types.Unique.Supply+import GHC.Utils.Misc+import GHC.Tc.Types+import GHC.Tc.Types.Origin+import GHC.Tc.Types.Constraint+import GHC.Core.Predicate++import GHC.Types.Unique.Set+import GHC.Core.TyCon.Env+import GHC.Data.Maybe++import GHC.Core.Map.Type+import GHC.Data.TrieMap++import Control.Monad+import GHC.Utils.Monad+import Data.IORef+import Data.List ( partition, mapAccumL )+import Data.List.NonEmpty ( NonEmpty(..), cons, toList, nonEmpty )+import qualified Data.List.NonEmpty as NE+import Control.Arrow ( first )++#if defined(DEBUG)+import GHC.Data.Graph.Directed+#endif++{-+************************************************************************+* *+* Worklists *+* Canonical and non-canonical constraints that the simplifier has to *+* work on. Including their simplification depths. *+* *+* *+************************************************************************++Note [WorkList priorities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~+A WorkList contains canonical and non-canonical items (of all flavours).+Notice that each Ct now has a simplification depth. We may+consider using this depth for prioritization as well in the future.++As a simple form of priority queue, our worklist separates out++* equalities (wl_eqs); see Note [Prioritise equalities]+* all the rest (wl_rest)++Note [Prioritise equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~+It's very important to process equalities /first/:++* (Efficiency) The general reason to do so is that if we process a+ class constraint first, we may end up putting it into the inert set+ and then kicking it out later. That's extra work compared to just+ doing the equality first.++* (Avoiding fundep iteration) As #14723 showed, it's possible to+ get non-termination if we+ - Emit the Derived fundep equalities for a class constraint,+ generating some fresh unification variables.+ - That leads to some unification+ - Which kicks out the class constraint+ - Which isn't solved (because there are still some more Derived+ equalities in the work-list), but generates yet more fundeps+ Solution: prioritise derived equalities over class constraints++* (Class equalities) We need to prioritise equalities even if they+ are hidden inside a class constraint;+ see Note [Prioritise class equalities]++* (Kick-out) We want to apply this priority scheme to kicked-out+ constraints too (see the call to extendWorkListCt in kick_out_rewritable+ E.g. a CIrredCan can be a hetero-kinded (t1 ~ t2), which may become+ homo-kinded when kicked out, and hence we want to prioritise it.++* (Derived equalities) Originally we tried to postpone processing+ Derived equalities, in the hope that we might never need to deal+ with them at all; but in fact we must process Derived equalities+ eagerly, partly for the (Efficiency) reason, and more importantly+ for (Avoiding fundep iteration).++Note [Prioritise class equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We prioritise equalities in the solver (see selectWorkItem). But class+constraints like (a ~ b) and (a ~~ b) are actually equalities too;+see Note [The equality types story] in GHC.Builtin.Types.Prim.++Failing to prioritise these is inefficient (more kick-outs etc).+But, worse, it can prevent us spotting a "recursive knot" among+Wanted constraints. See comment:10 of #12734 for a worked-out+example.++So we arrange to put these particular class constraints in the wl_eqs.++ NB: since we do not currently apply the substitution to the+ inert_solved_dicts, the knot-tying still seems a bit fragile.+ But this makes it better.++-}++-- See Note [WorkList priorities]+data WorkList+ = WL { wl_eqs :: [Ct] -- CEqCan, CDictCan, CIrredCan+ -- Given, Wanted, and Derived+ -- Contains both equality constraints and their+ -- class-level variants (a~b) and (a~~b);+ -- See Note [Prioritise equalities]+ -- See Note [Prioritise class equalities]++ , wl_rest :: [Ct]++ , wl_implics :: Bag Implication -- See Note [Residual implications]+ }++appendWorkList :: WorkList -> WorkList -> WorkList+appendWorkList+ (WL { wl_eqs = eqs1, wl_rest = rest1+ , wl_implics = implics1 })+ (WL { wl_eqs = eqs2, wl_rest = rest2+ , wl_implics = implics2 })+ = WL { wl_eqs = eqs1 ++ eqs2+ , wl_rest = rest1 ++ rest2+ , wl_implics = implics1 `unionBags` implics2 }++workListSize :: WorkList -> Int+workListSize (WL { wl_eqs = eqs, wl_rest = rest })+ = length eqs + length rest++extendWorkListEq :: Ct -> WorkList -> WorkList+extendWorkListEq ct wl = wl { wl_eqs = ct : wl_eqs wl }++extendWorkListNonEq :: Ct -> WorkList -> WorkList+-- Extension by non equality+extendWorkListNonEq ct wl = wl { wl_rest = ct : wl_rest wl }++extendWorkListDeriveds :: [CtEvidence] -> WorkList -> WorkList+extendWorkListDeriveds evs wl+ = extendWorkListCts (map mkNonCanonical evs) wl++extendWorkListImplic :: Implication -> WorkList -> WorkList+extendWorkListImplic implic wl = wl { wl_implics = implic `consBag` wl_implics wl }++extendWorkListCt :: Ct -> WorkList -> WorkList+-- Agnostic+extendWorkListCt ct wl+ = case classifyPredType (ctPred ct) of+ EqPred {}+ -> extendWorkListEq ct wl++ ClassPred cls _ -- See Note [Prioritise class equalities]+ | isEqPredClass cls+ -> extendWorkListEq ct wl++ _ -> extendWorkListNonEq ct wl++extendWorkListCts :: [Ct] -> WorkList -> WorkList+-- Agnostic+extendWorkListCts cts wl = foldr extendWorkListCt wl cts++isEmptyWorkList :: WorkList -> Bool+isEmptyWorkList (WL { wl_eqs = eqs, wl_rest = rest, wl_implics = implics })+ = null eqs && null rest && isEmptyBag implics++emptyWorkList :: WorkList+emptyWorkList = WL { wl_eqs = [], wl_rest = [], wl_implics = emptyBag }++selectWorkItem :: WorkList -> Maybe (Ct, WorkList)+-- See Note [Prioritise equalities]+selectWorkItem wl@(WL { wl_eqs = eqs, wl_rest = rest })+ | ct:cts <- eqs = Just (ct, wl { wl_eqs = cts })+ | ct:cts <- rest = Just (ct, wl { wl_rest = cts })+ | otherwise = Nothing++getWorkList :: TcS WorkList+getWorkList = do { wl_var <- getTcSWorkListRef+ ; wrapTcS (TcM.readTcRef wl_var) }++selectNextWorkItem :: TcS (Maybe Ct)+-- Pick which work item to do next+-- See Note [Prioritise equalities]+selectNextWorkItem+ = do { wl_var <- getTcSWorkListRef+ ; wl <- readTcRef wl_var+ ; case selectWorkItem wl of {+ Nothing -> return Nothing ;+ Just (ct, new_wl) ->+ do { -- checkReductionDepth (ctLoc ct) (ctPred ct)+ -- This is done by GHC.Tc.Solver.Interact.chooseInstance+ ; writeTcRef wl_var new_wl+ ; return (Just ct) } } }++-- Pretty printing+instance Outputable WorkList where+ ppr (WL { wl_eqs = eqs, wl_rest = rest, wl_implics = implics })+ = text "WL" <+> (braces $+ vcat [ ppUnless (null eqs) $+ text "Eqs =" <+> vcat (map ppr eqs)+ , ppUnless (null rest) $+ text "Non-eqs =" <+> vcat (map ppr rest)+ , ppUnless (isEmptyBag implics) $+ ifPprDebug (text "Implics =" <+> vcat (map ppr (bagToList implics)))+ (text "(Implics omitted)")+ ])+++{- *********************************************************************+* *+ InertSet: the inert set+* *+* *+********************************************************************* -}++data InertSet+ = IS { inert_cans :: InertCans+ -- Canonical Given, Wanted, Derived+ -- Sometimes called "the inert set"++ , inert_cycle_breakers :: [(TcTyVar, TcType)]+ -- a list of CycleBreakerTv / original family applications+ -- used to undo the cycle-breaking needed to handle+ -- Note [Type variable cycles in Givens] in GHC.Tc.Solver.Canonical++ , inert_famapp_cache :: FunEqMap (TcCoercion, TcType)+ -- Just a hash-cons cache for use when reducing family applications+ -- only+ --+ -- If F tys :-> (co, rhs, flav),+ -- then co :: rhs ~N F tys+ -- all evidence is from instances or Givens; no coercion holes here+ -- (We have no way of "kicking out" from the cache, so putting+ -- wanteds here means we can end up solving a Wanted with itself. Bad)++ , inert_solved_dicts :: DictMap CtEvidence+ -- All Wanteds, of form ev :: C t1 .. tn+ -- See Note [Solved dictionaries]+ -- and Note [Do not add superclasses of solved dictionaries]+ }++instance Outputable InertSet where+ ppr (IS { inert_cans = ics+ , inert_solved_dicts = solved_dicts })+ = vcat [ ppr ics+ , ppUnless (null dicts) $+ text "Solved dicts =" <+> vcat (map ppr dicts) ]+ where+ dicts = bagToList (dictsToBag solved_dicts)++emptyInertCans :: InertCans+emptyInertCans+ = IC { inert_eqs = emptyDVarEnv+ , inert_given_eq_lvl = topTcLevel+ , inert_given_eqs = False+ , inert_dicts = emptyDicts+ , inert_safehask = emptyDicts+ , inert_funeqs = emptyFunEqs+ , inert_insts = []+ , inert_irreds = emptyCts }++emptyInert :: InertSet+emptyInert+ = IS { inert_cans = emptyInertCans+ , inert_cycle_breakers = []+ , inert_famapp_cache = emptyFunEqs+ , inert_solved_dicts = emptyDictMap }+++{- Note [Solved dictionaries]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When we apply a top-level instance declaration, we add the "solved"+dictionary to the inert_solved_dicts. In general, we use it to avoid+creating a new EvVar when we have a new goal that we have solved in+the past.++But in particular, we can use it to create *recursive* dictionaries.+The simplest, degenerate case is+ instance C [a] => C [a] where ...+If we have+ [W] d1 :: C [x]+then we can apply the instance to get+ d1 = $dfCList d+ [W] d2 :: C [x]+Now 'd1' goes in inert_solved_dicts, and we can solve d2 directly from d1.+ d1 = $dfCList d+ d2 = d1++See Note [Example of recursive dictionaries]++VERY IMPORTANT INVARIANT:++ (Solved Dictionary Invariant)+ Every member of the inert_solved_dicts is the result+ of applying an instance declaration that "takes a step"++ An instance "takes a step" if it has the form+ dfunDList d1 d2 = MkD (...) (...) (...)+ That is, the dfun is lazy in its arguments, and guarantees to+ immediately return a dictionary constructor. NB: all dictionary+ data constructors are lazy in their arguments.++ This property is crucial to ensure that all dictionaries are+ non-bottom, which in turn ensures that the whole "recursive+ dictionary" idea works at all, even if we get something like+ rec { d = dfunDList d dx }+ See Note [Recursive superclasses] in GHC.Tc.TyCl.Instance.++ Reason:+ - All instances, except two exceptions listed below, "take a step"+ in the above sense++ - Exception 1: local quantified constraints have no such guarantee;+ indeed, adding a "solved dictionary" when appling a quantified+ constraint led to the ability to define unsafeCoerce+ in #17267.++ - Exception 2: the magic built-in instance for (~) has no+ such guarantee. It behaves as if we had+ class (a ~# b) => (a ~ b) where {}+ instance (a ~# b) => (a ~ b) where {}+ The "dfun" for the instance is strict in the coercion.+ Anyway there's no point in recording a "solved dict" for+ (t1 ~ t2); it's not going to allow a recursive dictionary+ to be constructed. Ditto (~~) and Coercible.++THEREFORE we only add a "solved dictionary"+ - when applying an instance declaration+ - subject to Exceptions 1 and 2 above++In implementation terms+ - GHC.Tc.Solver.Monad.addSolvedDict adds a new solved dictionary,+ conditional on the kind of instance++ - It is only called when applying an instance decl,+ in GHC.Tc.Solver.Interact.doTopReactDict++ - ClsInst.InstanceWhat says what kind of instance was+ used to solve the constraint. In particular+ * LocalInstance identifies quantified constraints+ * BuiltinEqInstance identifies the strange built-in+ instances for equality.++ - ClsInst.instanceReturnsDictCon says which kind of+ instance guarantees to return a dictionary constructor++Other notes about solved dictionaries++* See also Note [Do not add superclasses of solved dictionaries]++* The inert_solved_dicts field is not rewritten by equalities,+ so it may get out of date.++* The inert_solved_dicts are all Wanteds, never givens++* We only cache dictionaries from top-level instances, not from+ local quantified constraints. Reason: if we cached the latter+ we'd need to purge the cache when bringing new quantified+ constraints into scope, because quantified constraints "shadow"+ top-level instances.++Note [Do not add superclasses of solved dictionaries]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Every member of inert_solved_dicts is the result of applying a+dictionary function, NOT of applying superclass selection to anything.+Consider++ class Ord a => C a where+ instance Ord [a] => C [a] where ...++Suppose we are trying to solve+ [G] d1 : Ord a+ [W] d2 : C [a]++Then we'll use the instance decl to give++ [G] d1 : Ord a Solved: d2 : C [a] = $dfCList d3+ [W] d3 : Ord [a]++We must not add d4 : Ord [a] to the 'solved' set (by taking the+superclass of d2), otherwise we'll use it to solve d3, without ever+using d1, which would be a catastrophe.++Solution: when extending the solved dictionaries, do not add superclasses.+That's why each element of the inert_solved_dicts is the result of applying+a dictionary function.++Note [Example of recursive dictionaries]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+--- Example 1++ data D r = ZeroD | SuccD (r (D r));++ instance (Eq (r (D r))) => Eq (D r) where+ ZeroD == ZeroD = True+ (SuccD a) == (SuccD b) = a == b+ _ == _ = False;++ equalDC :: D [] -> D [] -> Bool;+ equalDC = (==);++We need to prove (Eq (D [])). Here's how we go:++ [W] d1 : Eq (D [])+By instance decl of Eq (D r):+ [W] d2 : Eq [D []] where d1 = dfEqD d2+By instance decl of Eq [a]:+ [W] d3 : Eq (D []) where d2 = dfEqList d3+ d1 = dfEqD d2+Now this wanted can interact with our "solved" d1 to get:+ d3 = d1++-- Example 2:+This code arises in the context of "Scrap Your Boilerplate with Class"++ class Sat a+ class Data ctx a+ instance Sat (ctx Char) => Data ctx Char -- dfunData1+ instance (Sat (ctx [a]), Data ctx a) => Data ctx [a] -- dfunData2++ class Data Maybe a => Foo a++ instance Foo t => Sat (Maybe t) -- dfunSat++ instance Data Maybe a => Foo a -- dfunFoo1+ instance Foo a => Foo [a] -- dfunFoo2+ instance Foo [Char] -- dfunFoo3++Consider generating the superclasses of the instance declaration+ instance Foo a => Foo [a]++So our problem is this+ [G] d0 : Foo t+ [W] d1 : Data Maybe [t] -- Desired superclass++We may add the given in the inert set, along with its superclasses+ Inert:+ [G] d0 : Foo t+ [G] d01 : Data Maybe t -- Superclass of d0+ WorkList+ [W] d1 : Data Maybe [t]++Solve d1 using instance dfunData2; d1 := dfunData2 d2 d3+ Inert:+ [G] d0 : Foo t+ [G] d01 : Data Maybe t -- Superclass of d0+ Solved:+ d1 : Data Maybe [t]+ WorkList:+ [W] d2 : Sat (Maybe [t])+ [W] d3 : Data Maybe t++Now, we may simplify d2 using dfunSat; d2 := dfunSat d4+ Inert:+ [G] d0 : Foo t+ [G] d01 : Data Maybe t -- Superclass of d0+ Solved:+ d1 : Data Maybe [t]+ d2 : Sat (Maybe [t])+ WorkList:+ [W] d3 : Data Maybe t+ [W] d4 : Foo [t]++Now, we can just solve d3 from d01; d3 := d01+ Inert+ [G] d0 : Foo t+ [G] d01 : Data Maybe t -- Superclass of d0+ Solved:+ d1 : Data Maybe [t]+ d2 : Sat (Maybe [t])+ WorkList+ [W] d4 : Foo [t]++Now, solve d4 using dfunFoo2; d4 := dfunFoo2 d5+ Inert+ [G] d0 : Foo t+ [G] d01 : Data Maybe t -- Superclass of d0+ Solved:+ d1 : Data Maybe [t]+ d2 : Sat (Maybe [t])+ d4 : Foo [t]+ WorkList:+ [W] d5 : Foo t++Now, d5 can be solved! d5 := d0++Result+ d1 := dfunData2 d2 d3+ d2 := dfunSat d4+ d3 := d01+ d4 := dfunFoo2 d5+ d5 := d0+-}++{- *********************************************************************+* *+ InertCans: the canonical inerts+* *+* *+********************************************************************* -}++data InertCans -- See Note [Detailed InertCans Invariants] for more+ = IC { inert_eqs :: InertEqs+ -- See Note [inert_eqs: the inert equalities]+ -- All CEqCans with a TyVarLHS; index is the LHS tyvar+ -- Domain = skolems and untouchables; a touchable would be unified++ , inert_funeqs :: FunEqMap EqualCtList+ -- All CEqCans with a TyFamLHS; index is the whole family head type.+ -- LHS is fully rewritten (modulo eqCanRewrite constraints)+ -- wrt inert_eqs+ -- Can include all flavours, [G], [W], [WD], [D]++ , inert_dicts :: DictMap Ct+ -- Dictionaries only+ -- All fully rewritten (modulo flavour constraints)+ -- wrt inert_eqs++ , inert_insts :: [QCInst]++ , inert_safehask :: DictMap Ct+ -- Failed dictionary resolution due to Safe Haskell overlapping+ -- instances restriction. We keep this separate from inert_dicts+ -- as it doesn't cause compilation failure, just safe inference+ -- failure.+ --+ -- ^ See Note [Safe Haskell Overlapping Instances Implementation]+ -- in "GHC.Tc.Solver"++ , inert_irreds :: Cts+ -- Irreducible predicates that cannot be made canonical,+ -- and which don't interact with others (e.g. (c a))+ -- and insoluble predicates (e.g. Int ~ Bool, or a ~ [a])++ , inert_given_eq_lvl :: TcLevel+ -- The TcLevel of the innermost implication that has a Given+ -- equality of the sort that make a unification variable untouchable+ -- (see Note [Unification preconditions] in GHC.Tc.Utils.Unify).+ -- See Note [Tracking Given equalities] below++ , inert_given_eqs :: Bool+ -- True <=> The inert Givens *at this level* (tcl_tclvl)+ -- could includes at least one equality /other than/ a+ -- let-bound skolem equality.+ -- Reason: report these givens when reporting a failed equality+ -- See Note [Tracking Given equalities]+ }++type InertEqs = DTyVarEnv EqualCtList++newtype EqualCtList = EqualCtList (NonEmpty Ct)+ deriving newtype Outputable+ -- See Note [EqualCtList invariants]++unitEqualCtList :: Ct -> EqualCtList+unitEqualCtList ct = EqualCtList (ct :| [])++addToEqualCtList :: Ct -> EqualCtList -> EqualCtList+-- NB: This function maintains the "derived-before-wanted" invariant of EqualCtList,+-- but not the others. See Note [EqualCtList invariants]+addToEqualCtList ct (EqualCtList old_eqs)+ | isWantedCt ct+ , eq1 :| eqs <- old_eqs+ = EqualCtList (eq1 :| ct : eqs)+ | otherwise+ = EqualCtList (ct `cons` old_eqs)++filterEqualCtList :: (Ct -> Bool) -> EqualCtList -> Maybe EqualCtList+filterEqualCtList pred (EqualCtList cts)+ = fmap EqualCtList (nonEmpty $ NE.filter pred cts)++equalCtListToList :: EqualCtList -> [Ct]+equalCtListToList (EqualCtList cts) = toList cts++listToEqualCtList :: [Ct] -> Maybe EqualCtList+-- NB: This does not maintain invariants other than having the EqualCtList be+-- non-empty+listToEqualCtList cts = EqualCtList <$> nonEmpty cts++{- Note [Tracking Given equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+For reasons described in (UNTOUCHABLE) in GHC.Tc.Utils.Unify+Note [Unification preconditions], we can't unify+ alpha[2] ~ Int+under a level-4 implication if there are any Given equalities+bound by the implications at level 3 of 4. To that end, the+InertCans tracks++ inert_given_eq_lvl :: TcLevel+ -- The TcLevel of the innermost implication that has a Given+ -- equality of the sort that make a unification variable untouchable+ -- (see Note [Unification preconditions] in GHC.Tc.Utils.Unify).++We update inert_given_eq_lvl whenever we add a Given to the+inert set, in updateGivenEqs.++Then a unification variable alpha[n] is untouchable iff+ n < inert_given_eq_lvl+that is, if the unification variable was born outside an+enclosing Given equality.++Exactly which constraints should trigger (UNTOUCHABLE), and hence+should update inert_given_eq_lvl?++* We do /not/ need to worry about let-bound skolems, such ast+ forall[2] a. a ~ [b] => blah+ See Note [Let-bound skolems]++* Consider an implication+ forall[2]. beta[1] => alpha[1] ~ Int+ where beta is a unification variable that has already been unified+ to () in an outer scope. Then alpha[1] is perfectly touchable and+ we can unify alpha := Int. So when deciding whether the givens contain+ an equality, we should canonicalise first, rather than just looking at+ the /original/ givens (#8644).++ * However, we must take account of *potential* equalities. Consider the+ same example again, but this time we have /not/ yet unified beta:+ forall[2] beta[1] => ...blah...++ Because beta might turn into an equality, updateGivenEqs conservatively+ treats it as a potential equality, and updates inert_give_eq_lvl++ * What about something like forall[2] a b. a ~ F b => [W] alpha[1] ~ X y z?++ That Given cannot affect the Wanted, because the Given is entirely+ *local*: it mentions only skolems bound in the very same+ implication. Such equalities need not make alpha untouchable. (Test+ case typecheck/should_compile/LocalGivenEqs has a real-life+ motivating example, with some detailed commentary.)+ Hence the 'mentionsOuterVar' test in updateGivenEqs.++ However, solely to support better error messages+ (see Note [HasGivenEqs] in GHC.Tc.Types.Constraint) we also track+ these "local" equalities in the boolean inert_given_eqs field.+ This field is used only to set the ic_given_eqs field to LocalGivenEqs;+ see the function getHasGivenEqs.++ Here is a simpler case that triggers this behaviour:++ data T where+ MkT :: F a ~ G b => a -> b -> T++ f (MkT _ _) = True++ Because of this behaviour around local equality givens, we can infer the+ type of f. This is typecheck/should_compile/LocalGivenEqs2.++ * We need not look at the equality relation involved (nominal vs+ representational), because representational equalities can still+ imply nominal ones. For example, if (G a ~R G b) and G's argument's+ role is nominal, then we can deduce a ~N b.++Note [Let-bound skolems]+~~~~~~~~~~~~~~~~~~~~~~~~+If * the inert set contains a canonical Given CEqCan (a ~ ty)+and * 'a' is a skolem bound in this very implication,++then:+a) The Given is pretty much a let-binding, like+ f :: (a ~ b->c) => a -> a+ Here the equality constraint is like saying+ let a = b->c in ...+ It is not adding any new, local equality information,+ and hence can be ignored by has_given_eqs++b) 'a' will have been completely substituted out in the inert set,+ so we can safely discard it.++For an example, see #9211.++See also GHC.Tc.Utils.Unify Note [Deeper level on the left] for how we ensure+that the right variable is on the left of the equality when both are+tyvars.++You might wonder whether the skolem really needs to be bound "in the+very same implication" as the equuality constraint.+Consider this (c.f. #15009):++ data S a where+ MkS :: (a ~ Int) => S a++ g :: forall a. S a -> a -> blah+ g x y = let h = \z. ( z :: Int+ , case x of+ MkS -> [y,z])+ in ...++From the type signature for `g`, we get `y::a` . Then when we+encounter the `\z`, we'll assign `z :: alpha[1]`, say. Next, from the+body of the lambda we'll get++ [W] alpha[1] ~ Int -- From z::Int+ [W] forall[2]. (a ~ Int) => [W] alpha[1] ~ a -- From [y,z]++Now, unify alpha := a. Now we are stuck with an unsolved alpha~Int!+So we must treat alpha as untouchable under the forall[2] implication.++Note [Detailed InertCans Invariants]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The InertCans represents a collection of constraints with the following properties:++ * All canonical++ * No two dictionaries with the same head+ * No two CIrreds with the same type++ * Family equations inert wrt top-level family axioms++ * Dictionaries have no matching top-level instance++ * Given family or dictionary constraints don't mention touchable+ unification variables++ * Non-CEqCan constraints are fully rewritten with respect+ to the CEqCan equalities (modulo eqCanRewrite of course;+ eg a wanted cannot rewrite a given)++ * CEqCan equalities: see Note [inert_eqs: the inert equalities]+ Also see documentation in Constraint.Ct for a list of invariants++Note [EqualCtList invariants]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ * All are equalities+ * All these equalities have the same LHS+ * The list is never empty+ * No element of the list can rewrite any other+ * Derived before Wanted++From the fourth invariant it follows that the list is+ - A single [G], or+ - Zero or one [D] or [WD], followed by any number of [W]++The Wanteds can't rewrite anything which is why we put them last++Note [inert_eqs: the inert equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Definition [Can-rewrite relation]+A "can-rewrite" relation between flavours, written f1 >= f2, is a+binary relation with the following properties++ (R1) >= is transitive+ (R2) If f1 >= f, and f2 >= f,+ then either f1 >= f2 or f2 >= f1++Lemma. If f1 >= f then f1 >= f1+Proof. By property (R2), with f1=f2++Definition [Generalised substitution]+A "generalised substitution" S is a set of triples (t0 -f-> t), where+ t0 is a type variable or an exactly-saturated type family application+ (that is, t0 is a CanEqLHS)+ t is a type+ f is a flavour+such that+ (WF1) if (t0 -f1-> t1) in S+ (t0' -f2-> t2) in S+ then either not (f1 >= f2) or t0 does not appear within t0'+ (WF2) if (t0 -f-> t) is in S, then t /= t0++Definition [Applying a generalised substitution]+If S is a generalised substitution+ S(f,t0) = t, if (t0 -fs-> t) in S, and fs >= f+ = apply S to components of t0, otherwise+See also Note [Flavours with roles].++Theorem: S(f,t0) is well defined as a function.+Proof: Suppose (t0 -f1-> t1) and (t0 -f2-> t2) are both in S,+ and f1 >= f and f2 >= f+ Then by (R2) f1 >= f2 or f2 >= f1, which contradicts (WF1)++Notation: repeated application.+ S^0(f,t) = t+ S^(n+1)(f,t) = S(f, S^n(t))++Definition: inert generalised substitution+A generalised substitution S is "inert" iff++ (IG1) there is an n such that+ for every f,t, S^n(f,t) = S^(n+1)(f,t)++By (IG1) we define S*(f,t) to be the result of exahaustively+applying S(f,_) to t.++----------------------------------------------------------------+Our main invariant:+ the inert CEqCans should be an inert generalised substitution+----------------------------------------------------------------++Note that inertness is not the same as idempotence. To apply S to a+type, you may have to apply it recursively. But inertness does+guarantee that this recursive use will terminate.++Note [Extending the inert equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Main Theorem [Stability under extension]+ Suppose we have a "work item"+ t0 -fw-> t+ and an inert generalised substitution S,+ THEN the extended substitution T = S+(t0 -fw-> t)+ is an inert generalised substitution+ PROVIDED+ (T1) S(fw,t0) = t0 -- LHS of work-item is a fixpoint of S(fw,_)+ (T2) S(fw,t) = t -- RHS of work-item is a fixpoint of S(fw,_)+ (T3) t0 not in t -- No occurs check in the work item++ AND, for every (t0' -fs-> s) in S:+ (K0) not (fw >= fs)+ Reason: suppose we kick out (a -fs-> s),+ and add (t0 -fw-> t) to the inert set.+ The latter can't rewrite the former,+ so the kick-out achieved nothing++ OR { (K1) t0 is not rewritable in t0'. That is, t0 does not occur+ in t0' (except perhaps in a cast or coercion).+ Reason: if fw >= fs, WF1 says we can't have both+ t0 -fw-> t and F t0 -fs-> s++ AND (K2): guarantees inertness of the new substitution+ { (K2a) not (fs >= fs)+ OR (K2b) fs >= fw+ OR (K2d) t0 not in s }++ AND (K3) See Note [K3: completeness of solving]+ { (K3a) If the role of fs is nominal: s /= t0+ (K3b) If the role of fs is representational:+ s is not of form (t0 t1 .. tn) } }+++Conditions (T1-T3) are established by the canonicaliser+Conditions (K1-K3) are established by GHC.Tc.Solver.Monad.kickOutRewritable++The idea is that+* (T1-2) are guaranteed by exhaustively rewriting the work-item+ with S(fw,_).++* T3 is guaranteed by a simple occurs-check on the work item.+ This is done during canonicalisation, in canEqCanLHSFinish; invariant+ (TyEq:OC) of CEqCan.++* (K1-3) are the "kick-out" criteria. (As stated, they are really the+ "keep" criteria.) If the current inert S contains a triple that does+ not satisfy (K1-3), then we remove it from S by "kicking it out",+ and re-processing it.++* Note that kicking out is a Bad Thing, because it means we have to+ re-process a constraint. The less we kick out, the better.+ TODO: Make sure that kicking out really *is* a Bad Thing. We've assumed+ this but haven't done the empirical study to check.++* Assume we have G>=G, G>=W and that's all. Then, when performing+ a unification we add a new given a -G-> ty. But doing so does NOT require+ us to kick out an inert wanted that mentions a, because of (K2a). This+ is a common case, hence good not to kick out.++* Lemma (L2): if not (fw >= fw), then K0 holds and we kick out nothing+ Proof: using Definition [Can-rewrite relation], fw can't rewrite anything+ and so K0 holds. Intuitively, since fw can't rewrite anything,+ adding it cannot cause any loops+ This is a common case, because Wanteds cannot rewrite Wanteds.+ It's used to avoid even looking for constraint to kick out.++* Lemma (L1): The conditions of the Main Theorem imply that there is no+ (t0 -fs-> t) in S, s.t. (fs >= fw).+ Proof. Suppose the contrary (fs >= fw). Then because of (T1),+ S(fw,t0)=t0. But since fs>=fw, S(fw,t0) = s, hence s=t0. But now we+ have (t0 -fs-> t0) in S, which contradicts (WF2).++* The extended substitution satisfies (WF1) and (WF2)+ - (K1) plus (L1) guarantee that the extended substitution satisfies (WF1).+ - (T3) guarantees (WF2).++* (K2) is about inertness. Intuitively, any infinite chain T^0(f,t),+ T^1(f,t), T^2(f,T).... must pass through the new work item infinitely+ often, since the substitution without the work item is inert; and must+ pass through at least one of the triples in S infinitely often.++ - (K2a): if not(fs>=fs) then there is no f that fs can rewrite (fs>=f),+ and hence this triple never plays a role in application S(f,a).+ It is always safe to extend S with such a triple.++ (NB: we could strengten K1) in this way too, but see K3.++ - (K2b): If this holds then, by (T2), b is not in t. So applying the+ work item does not generate any new opportunities for applying S++ - (K2c): If this holds, we can't pass through this triple infinitely+ often, because if we did then fs>=f, fw>=f, hence by (R2)+ * either fw>=fs, contradicting K2c+ * or fs>=fw; so by the argument in K2b we can't have a loop++ - (K2d): if a not in s, we hae no further opportunity to apply the+ work item, similar to (K2b)++ NB: Dimitrios has a PDF that does this in more detail++Key lemma to make it watertight.+ Under the conditions of the Main Theorem,+ forall f st fw >= f, a is not in S^k(f,t), for any k++Also, consider roles more carefully. See Note [Flavours with roles]++Note [K3: completeness of solving]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+(K3) is not necessary for the extended substitution+to be inert. In fact K1 could be made stronger by saying+ ... then (not (fw >= fs) or not (fs >= fs))+But it's not enough for S to be inert; we also want completeness.+That is, we want to be able to solve all soluble wanted equalities.+Suppose we have++ work-item b -G-> a+ inert-item a -W-> b++Assuming (G >= W) but not (W >= W), this fulfills all the conditions,+so we could extend the inerts, thus:++ inert-items b -G-> a+ a -W-> b++But if we kicked-out the inert item, we'd get++ work-item a -W-> b+ inert-item b -G-> a++Then rewrite the work-item gives us (a -W-> a), which is soluble via Refl.+So we add one more clause to the kick-out criteria++Another way to understand (K3) is that we treat an inert item+ a -f-> b+in the same way as+ b -f-> a+So if we kick out one, we should kick out the other. The orientation+is somewhat accidental.++When considering roles, we also need the second clause (K3b). Consider++ work-item c -G/N-> a+ inert-item a -W/R-> b c++The work-item doesn't get rewritten by the inert, because (>=) doesn't hold.+But we don't kick out the inert item because not (W/R >= W/R). So we just+add the work item. But then, consider if we hit the following:++ work-item b -G/N-> Id+ inert-items a -W/R-> b c+ c -G/N-> a+where+ newtype Id x = Id x++For similar reasons, if we only had (K3a), we wouldn't kick the+representational inert out. And then, we'd miss solving the inert, which+now reduced to reflexivity.++The solution here is to kick out representational inerts whenever the+tyvar of a work item is "exposed", where exposed means being at the+head of the top-level application chain (a t1 .. tn). See+is_can_eq_lhs_head. This is encoded in (K3b).++Beware: if we make this test succeed too often, we kick out too much,+and the solver might loop. Consider (#14363)+ work item: [G] a ~R f b+ inert item: [G] b ~R f a+In GHC 8.2 the completeness tests more aggressive, and kicked out+the inert item; but no rewriting happened and there was an infinite+loop. All we need is to have the tyvar at the head.++Note [Flavours with roles]+~~~~~~~~~~~~~~~~~~~~~~~~~~+The system described in Note [inert_eqs: the inert equalities]+discusses an abstract+set of flavours. In GHC, flavours have two components: the flavour proper,+taken from {Wanted, Derived, Given} and the equality relation (often called+role), taken from {NomEq, ReprEq}.+When substituting w.r.t. the inert set,+as described in Note [inert_eqs: the inert equalities],+we must be careful to respect all components of a flavour.+For example, if we have++ inert set: a -G/R-> Int+ b -G/R-> Bool++ type role T nominal representational++and we wish to compute S(W/R, T a b), the correct answer is T a Bool, NOT+T Int Bool. The reason is that T's first parameter has a nominal role, and+thus rewriting a to Int in T a b is wrong. Indeed, this non-congruence of+substitution means that the proof in Note [The inert equalities] may need+to be revisited, but we don't think that the end conclusion is wrong.+-}++instance Outputable InertCans where+ ppr (IC { inert_eqs = eqs+ , inert_funeqs = funeqs, inert_dicts = dicts+ , inert_safehask = safehask, inert_irreds = irreds+ , inert_given_eq_lvl = ge_lvl+ , inert_given_eqs = given_eqs+ , inert_insts = insts })++ = braces $ vcat+ [ ppUnless (isEmptyDVarEnv eqs) $+ text "Equalities:"+ <+> pprCts (foldDVarEnv folder emptyCts eqs)+ , ppUnless (isEmptyTcAppMap funeqs) $+ text "Type-function equalities =" <+> pprCts (foldFunEqs folder funeqs emptyCts)+ , ppUnless (isEmptyTcAppMap dicts) $+ text "Dictionaries =" <+> pprCts (dictsToBag dicts)+ , ppUnless (isEmptyTcAppMap safehask) $+ text "Safe Haskell unsafe overlap =" <+> pprCts (dictsToBag safehask)+ , ppUnless (isEmptyCts irreds) $+ text "Irreds =" <+> pprCts irreds+ , ppUnless (null insts) $+ text "Given instances =" <+> vcat (map ppr insts)+ , text "Innermost given equalities =" <+> ppr ge_lvl+ , text "Given eqs at this level =" <+> ppr given_eqs+ ]+ where+ folder (EqualCtList eqs) rest = nonEmptyToBag eqs `andCts` rest++{- *********************************************************************+* *+ Shadow constraints and improvement+* *+************************************************************************++Note [The improvement story and derived shadows]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Because Wanteds cannot rewrite Wanteds (see Note [Wanteds do not+rewrite Wanteds] in GHC.Tc.Types.Constraint), we may miss some opportunities for+solving. Here's a classic example (indexed-types/should_fail/T4093a)++ Ambiguity check for f: (Foo e ~ Maybe e) => Foo e++ We get [G] Foo e ~ Maybe e (CEqCan)+ [W] Foo ee ~ Foo e (CEqCan) -- ee is a unification variable+ [W] Foo ee ~ Maybe ee (CEqCan)++ The first Wanted gets rewritten to++ [W] Foo ee ~ Maybe e++ But now we appear to be stuck, since we don't rewrite Wanteds with+ Wanteds. This is silly because we can see that ee := e is the+ only solution.++The basic plan is+ * generate Derived constraints that shadow Wanted constraints+ * allow Derived to rewrite Derived+ * in order to cause some unifications to take place+ * that in turn solve the original Wanteds++The ONLY reason for all these Derived equalities is to tell us how to+unify a variable: that is, what Mark Jones calls "improvement".++The same idea is sometimes also called "saturation"; find all the+equalities that must hold in any solution.++Or, equivalently, you can think of the derived shadows as implementing+the "model": a non-idempotent but no-occurs-check substitution,+reflecting *all* *Nominal* equalities (a ~N ty) that are not+immediately soluble by unification.++More specifically, here's how it works (Oct 16):++* Wanted constraints are born as [WD]; this behaves like a+ [W] and a [D] paired together.++* When we are about to add a [WD] to the inert set, if it can+ be rewritten by a [D] a ~ ty, then we split it into [W] and [D],+ putting the latter into the work list (see maybeEmitShadow).++In the example above, we get to the point where we are stuck:+ [WD] Foo ee ~ Foo e+ [WD] Foo ee ~ Maybe ee++But now when [WD] Foo ee ~ Maybe ee is about to be added, we'll+split it into [W] and [D], since the inert [WD] Foo ee ~ Foo e+can rewrite it. Then:+ work item: [D] Foo ee ~ Maybe ee+ inert: [W] Foo ee ~ Maybe ee+ [WD] Foo ee ~ Maybe e++See Note [Splitting WD constraints]. Now the work item is rewritten+by the [WD] and we soon get ee := e.++Additional notes:++ * The derived shadow equalities live in inert_eqs, along with+ the Givens and Wanteds; see Note [EqualCtList invariants].++ * We make Derived shadows only for Wanteds, not Givens. So we+ have only [G], not [GD] and [G] plus splitting. See+ Note [Add derived shadows only for Wanteds]++ * We also get Derived equalities from functional dependencies+ and type-function injectivity; see calls to unifyDerived.++ * It's worth having [WD] rather than just [W] and [D] because+ * efficiency: silly to process the same thing twice+ * inert_dicts is a finite map keyed by+ the type; it's inconvenient for it to map to TWO constraints++Another example requiring Deriveds is in+Note [Put touchable variables on the left] in GHC.Tc.Solver.Canonical.++Note [Splitting WD constraints]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We are about to add a [WD] constraint to the inert set; and we+know that the inert set has fully rewritten it. Should we split+it into [W] and [D], and put the [D] in the work list for further+work?++* CDictCan (C tys):+ Yes if the inert set could rewrite tys to make the class constraint,+ or type family, fire. That is, yes if the inert_eqs intersects+ with the free vars of tys. For this test we use+ (anyRewritableTyVar True) which ignores casts and coercions in tys,+ because rewriting the casts or coercions won't make the thing fire+ more often.++* CEqCan (lhs ~ ty): Yes if the inert set could rewrite 'lhs' or 'ty'.+ We need to check both 'lhs' and 'ty' against the inert set:+ - Inert set contains [D] a ~ ty2+ Then we want to put [D] a ~ ty in the worklist, so we'll+ get [D] ty ~ ty2 with consequent good things++ - Inert set contains [D] b ~ a, where b is in ty.+ We can't just add [WD] a ~ ty[b] to the inert set, because+ that breaks the inert-set invariants. If we tried to+ canonicalise another [D] constraint mentioning 'a', we'd+ get an infinite loop++ Moreover we must use (anyRewritableTyVar False) for the RHS,+ because even tyvars in the casts and coercions could give+ an infinite loop if we don't expose it++* CIrredCan: Yes if the inert set can rewrite the constraint.+ We used to think splitting irreds was unnecessary, but+ see Note [Splitting Irred WD constraints]++* Others: nothing is gained by splitting.++Note [Splitting Irred WD constraints]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Splitting Irred constraints can make a difference. Here is the+scenario:++ a[sk] :: F v -- F is a type family+ beta :: alpha++ work item: [WD] a ~ beta++This is heterogeneous, so we emit a kind equality and make the work item an+inert Irred.++ work item: [D] F v ~ alpha+ inert: [WD] (a |> co) ~ beta (CIrredCan)++Can't make progress on the work item. Add to inert set. This kicks out the+old inert, because a [D] can rewrite a [WD].++ work item: [WD] (a |> co) ~ beta+ inert: [D] F v ~ alpha (CEqCan)++Can't make progress on this work item either (although GHC tries by+decomposing the cast and rewriting... but that doesn't make a difference),+which is still hetero. Emit a new kind equality and add to inert set. But,+critically, we split the Irred.++ work list:+ [D] F v ~ alpha (CEqCan)+ [D] (a |> co) ~ beta (CIrred) -- this one was split off+ inert:+ [W] (a |> co) ~ beta+ [D] F v ~ alpha++We quickly solve the first work item, as it's the same as an inert.++ work item: [D] (a |> co) ~ beta+ inert:+ [W] (a |> co) ~ beta+ [D] F v ~ alpha++We decompose the cast, yielding++ [D] a ~ beta++We then rewrite the kinds. The lhs kind is F v, which flattens to alpha.++ co' :: F v ~ alpha+ [D] (a |> co') ~ beta++Now this equality is homo-kinded. So we swizzle it around to++ [D] beta ~ (a |> co')++and set beta := a |> co', and go home happy.++If we don't split the Irreds, we loop. This is all dangerously subtle.++This is triggered by test case typecheck/should_compile/SplitWD.++Note [Add derived shadows only for Wanteds]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We only add shadows for Wanted constraints. That is, we have+[WD] but not [GD]; and maybeEmitShaodw looks only at [WD]+constraints.++It does just possibly make sense ot add a derived shadow for a+Given. If we created a Derived shadow of a Given, it could be+rewritten by other Deriveds, and that could, conceivably, lead to a+useful unification.++But (a) I have been unable to come up with an example of this+ happening+ (b) see #12660 for how adding the derived shadows+ of a Given led to an infinite loop.+ (c) It's unlikely that rewriting derived Givens will lead+ to a unification because Givens don't mention touchable+ unification variables++For (b) there may be other ways to solve the loop, but simply+reraining from adding derived shadows of Givens is particularly+simple. And it's more efficient too!++Still, here's one possible reason for adding derived shadows+for Givens. Consider+ work-item [G] a ~ [b], inerts has [D] b ~ a.+If we added the derived shadow (into the work list)+ [D] a ~ [b]+When we process it, we'll rewrite to a ~ [a] and get an+occurs check. Without it we'll miss the occurs check (reporting+inaccessible code); but that's probably OK.++Note [Keep CDictCan shadows as CDictCan]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we have+ class C a => D a b+and [G] D a b, [G] C a in the inert set. Now we insert+[D] b ~ c. We want to kick out a derived shadow for [D] D a b,+so we can rewrite it with the new constraint, and perhaps get+instance reduction or other consequences.++BUT we do not want to kick out a *non-canonical* (D a b). If we+did, we would do this:+ - rewrite it to [D] D a c, with pend_sc = True+ - use expandSuperClasses to add C a+ - go round again, which solves C a from the givens+This loop goes on for ever and triggers the simpl_loop limit.++Solution: kick out the CDictCan which will have pend_sc = False,+because we've already added its superclasses. So we won't re-add+them. If we forget the pend_sc flag, our cunning scheme for avoiding+generating superclasses repeatedly will fail.++See #11379 for a case of this.++Note [Do not do improvement for WOnly]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We do improvement between two constraints (e.g. for injectivity+or functional dependencies) only if both are "improvable". And+we improve a constraint wrt the top-level instances only if+it is improvable.++Improvable: [G] [WD] [D}+Not improvable: [W]++Reasons:++* It's less work: fewer pairs to compare++* Every [W] has a shadow [D] so nothing is lost++* Consider [WD] C Int b, where 'b' is a skolem, and+ class C a b | a -> b+ instance C Int Bool+ We'll do a fundep on it and emit [D] b ~ Bool+ That will kick out constraint [WD] C Int b+ Then we'll split it to [W] C Int b (keep in inert)+ and [D] C Int b (in work list)+ When processing the latter we'll rewrite it to+ [D] C Int Bool+ At that point it would be /stupid/ to interact it+ with the inert [W] C Int b in the inert set; after all,+ it's the very constraint from which the [D] C Int Bool+ was split! We can avoid this by not doing improvement+ on [W] constraints. This came up in #12860.+-}++maybeEmitShadow :: InertCans -> Ct -> TcS Ct+-- See Note [The improvement story and derived shadows]+maybeEmitShadow ics ct+ | let ev = ctEvidence ct+ , CtWanted { ctev_pred = pred, ctev_loc = loc+ , ctev_nosh = WDeriv } <- ev+ , shouldSplitWD (inert_eqs ics) (inert_funeqs ics) ct+ = do { traceTcS "Emit derived shadow" (ppr ct)+ ; let derived_ev = CtDerived { ctev_pred = pred+ , ctev_loc = loc }+ shadow_ct = ct { cc_ev = derived_ev }+ -- Te shadow constraint keeps the canonical shape.+ -- This just saves work, but is sometimes important;+ -- see Note [Keep CDictCan shadows as CDictCan]+ ; emitWork [shadow_ct]++ ; let ev' = ev { ctev_nosh = WOnly }+ ct' = ct { cc_ev = ev' }+ -- Record that it now has a shadow+ -- This is /the/ place we set the flag to WOnly+ ; return ct' }++ | otherwise+ = return ct++shouldSplitWD :: InertEqs -> FunEqMap EqualCtList -> Ct -> Bool+-- Precondition: 'ct' is [WD], and is inert+-- True <=> we should split ct ito [W] and [D] because+-- the inert_eqs can make progress on the [D]+-- See Note [Splitting WD constraints]++shouldSplitWD inert_eqs fun_eqs (CDictCan { cc_tyargs = tys })+ = should_split_match_args inert_eqs fun_eqs tys+ -- NB True: ignore coercions+ -- See Note [Splitting WD constraints]++shouldSplitWD inert_eqs fun_eqs (CEqCan { cc_lhs = TyVarLHS tv, cc_rhs = ty+ , cc_eq_rel = eq_rel })+ = tv `elemDVarEnv` inert_eqs+ || anyRewritableCanEqLHS eq_rel (canRewriteTv inert_eqs) (canRewriteTyFam fun_eqs) ty+ -- NB False: do not ignore casts and coercions+ -- See Note [Splitting WD constraints]++shouldSplitWD inert_eqs fun_eqs (CEqCan { cc_ev = ev, cc_eq_rel = eq_rel })+ = anyRewritableCanEqLHS eq_rel (canRewriteTv inert_eqs) (canRewriteTyFam fun_eqs)+ (ctEvPred ev)++shouldSplitWD inert_eqs fun_eqs (CIrredCan { cc_ev = ev })+ = anyRewritableCanEqLHS (ctEvEqRel ev) (canRewriteTv inert_eqs)+ (canRewriteTyFam fun_eqs) (ctEvPred ev)++shouldSplitWD _ _ _ = False -- No point in splitting otherwise++should_split_match_args :: InertEqs -> FunEqMap EqualCtList -> [TcType] -> Bool+-- True if the inert_eqs can rewrite anything in the argument types+should_split_match_args inert_eqs fun_eqs tys+ = any (anyRewritableCanEqLHS NomEq (canRewriteTv inert_eqs) (canRewriteTyFam fun_eqs)) tys+ -- See Note [Splitting WD constraints]++canRewriteTv :: InertEqs -> EqRel -> TyVar -> Bool+canRewriteTv inert_eqs eq_rel tv+ | Just (EqualCtList (ct :| _)) <- lookupDVarEnv inert_eqs tv+ , CEqCan { cc_eq_rel = eq_rel1 } <- ct+ = eq_rel1 `eqCanRewrite` eq_rel+ | otherwise+ = False++canRewriteTyFam :: FunEqMap EqualCtList -> EqRel -> TyCon -> [Type] -> Bool+canRewriteTyFam fun_eqs eq_rel tf args+ | Just (EqualCtList (ct :| _)) <- findFunEq fun_eqs tf args+ , CEqCan { cc_eq_rel = eq_rel1 } <- ct+ = eq_rel1 `eqCanRewrite` eq_rel+ | otherwise+ = False++isImprovable :: CtEvidence -> Bool+-- See Note [Do not do improvement for WOnly]+isImprovable (CtWanted { ctev_nosh = WOnly }) = False+isImprovable _ = True+++{- *********************************************************************+* *+ Inert equalities+* *+********************************************************************* -}++addTyEq :: InertEqs -> TcTyVar -> Ct -> InertEqs+addTyEq old_eqs tv ct+ = extendDVarEnv_C add_eq old_eqs tv (unitEqualCtList ct)+ where+ add_eq old_eqs _ = addToEqualCtList ct old_eqs++addCanFunEq :: FunEqMap EqualCtList -> TyCon -> [TcType] -> Ct+ -> FunEqMap EqualCtList+addCanFunEq old_eqs fun_tc fun_args ct+ = alterTcApp old_eqs fun_tc fun_args upd+ where+ upd (Just old_equal_ct_list) = Just $ addToEqualCtList ct old_equal_ct_list+ upd Nothing = Just $ unitEqualCtList ct++foldTyEqs :: (Ct -> b -> b) -> InertEqs -> b -> b+foldTyEqs k eqs z+ = foldDVarEnv (\(EqualCtList cts) z -> foldr k z cts) z eqs++findTyEqs :: InertCans -> TyVar -> [Ct]+findTyEqs icans tv = maybe [] id (fmap @Maybe equalCtListToList $+ lookupDVarEnv (inert_eqs icans) tv)++delEq :: InertCans -> CanEqLHS -> TcType -> InertCans+delEq ic lhs rhs = case lhs of+ TyVarLHS tv+ -> ic { inert_eqs = alterDVarEnv upd (inert_eqs ic) tv }+ TyFamLHS tf args+ -> ic { inert_funeqs = alterTcApp (inert_funeqs ic) tf args upd }+ where+ isThisOne :: Ct -> Bool+ isThisOne (CEqCan { cc_rhs = t1 }) = tcEqTypeNoKindCheck rhs t1+ isThisOne other = pprPanic "delEq" (ppr lhs $$ ppr ic $$ ppr other)++ upd :: Maybe EqualCtList -> Maybe EqualCtList+ upd (Just eq_ct_list) = filterEqualCtList (not . isThisOne) eq_ct_list+ upd Nothing = Nothing++findEq :: InertCans -> CanEqLHS -> [Ct]+findEq icans (TyVarLHS tv) = findTyEqs icans tv+findEq icans (TyFamLHS fun_tc fun_args)+ = maybe [] id (fmap @Maybe equalCtListToList $+ findFunEq (inert_funeqs icans) fun_tc fun_args)++{- *********************************************************************+* *+ Inert instances: inert_insts+* *+********************************************************************* -}++addInertForAll :: QCInst -> TcS ()+-- Add a local Given instance, typically arising from a type signature+addInertForAll new_qci+ = do { ics <- getInertCans+ ; ics1 <- add_qci ics++ -- Update given equalities. C.f updateGivenEqs+ ; tclvl <- getTcLevel+ ; let pred = qci_pred new_qci+ not_equality = isClassPred pred && not (isEqPred pred)+ -- True <=> definitely not an equality+ -- A qci_pred like (f a) might be an equality++ ics2 | not_equality = ics1+ | otherwise = ics1 { inert_given_eq_lvl = tclvl+ , inert_given_eqs = True }++ ; setInertCans ics2 }+ where+ add_qci :: InertCans -> TcS InertCans+ -- See Note [Do not add duplicate quantified instances]+ add_qci ics@(IC { inert_insts = qcis })+ | any same_qci qcis+ = do { traceTcS "skipping duplicate quantified instance" (ppr new_qci)+ ; return ics }++ | otherwise+ = do { traceTcS "adding new inert quantified instance" (ppr new_qci)+ ; return (ics { inert_insts = new_qci : qcis }) }++ same_qci old_qci = tcEqType (ctEvPred (qci_ev old_qci))+ (ctEvPred (qci_ev new_qci))++{- Note [Do not add duplicate quantified instances]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider this (#15244):++ f :: (C g, D g) => ....+ class S g => C g where ...+ class S g => D g where ...+ class (forall a. Eq a => Eq (g a)) => S g where ...++Then in f's RHS there are two identical quantified constraints+available, one via the superclasses of C and one via the superclasses+of D. The two are identical, and it seems wrong to reject the program+because of that. But without doing duplicate-elimination we will have+two matching QCInsts when we try to solve constraints arising from f's+RHS.++The simplest thing is simply to eliminate duplicates, which we do here.+-}++{- *********************************************************************+* *+ Adding an inert+* *+************************************************************************++Note [Adding an equality to the InertCans]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When adding an equality to the inerts:++* Split [WD] into [W] and [D] if the inerts can rewrite the latter;+ done by maybeEmitShadow.++* Kick out any constraints that can be rewritten by the thing+ we are adding. Done by kickOutRewritable.++* Note that unifying a:=ty, is like adding [G] a~ty; just use+ kickOutRewritable with Nominal, Given. See kickOutAfterUnification.+-}++addInertCan :: Ct -> TcS ()+-- Precondition: item /is/ canonical+-- See Note [Adding an equality to the InertCans]+addInertCan ct+ = do { traceTcS "addInertCan {" $+ text "Trying to insert new inert item:" <+> ppr ct++ ; ics <- getInertCans+ ; ct <- maybeEmitShadow ics ct+ ; ics <- maybeKickOut ics ct+ ; tclvl <- getTcLevel+ ; setInertCans (add_item tclvl ics ct)++ ; traceTcS "addInertCan }" $ empty }++maybeKickOut :: InertCans -> Ct -> TcS InertCans+-- For a CEqCan, kick out any inert that can be rewritten by the CEqCan+maybeKickOut ics ct+ | CEqCan { cc_lhs = lhs, cc_ev = ev, cc_eq_rel = eq_rel } <- ct+ = do { (_, ics') <- kickOutRewritable (ctEvFlavour ev, eq_rel) lhs ics+ ; return ics' }+ | otherwise+ = return ics++add_item :: TcLevel -> InertCans -> Ct -> InertCans+add_item tc_lvl+ ics@(IC { inert_funeqs = funeqs, inert_eqs = eqs })+ item@(CEqCan { cc_lhs = lhs })+ = updateGivenEqs tc_lvl item $+ case lhs of+ TyFamLHS tc tys -> ics { inert_funeqs = addCanFunEq funeqs tc tys item }+ TyVarLHS tv -> ics { inert_eqs = addTyEq eqs tv item }++add_item tc_lvl ics@(IC { inert_irreds = irreds }) item@(CIrredCan {})+ = updateGivenEqs tc_lvl item $ -- An Irred might turn out to be an+ -- equality, so we play safe+ ics { inert_irreds = irreds `Bag.snocBag` item }++add_item _ ics item@(CDictCan { cc_class = cls, cc_tyargs = tys })+ = ics { inert_dicts = addDict (inert_dicts ics) cls tys item }++add_item _ _ item+ = pprPanic "upd_inert set: can't happen! Inserting " $+ ppr item -- Can't be CNonCanonical because they only land in inert_irreds++updateGivenEqs :: TcLevel -> Ct -> InertCans -> InertCans+-- Set the inert_given_eq_level to the current level (tclvl)+-- if the constraint is a given equality that should prevent+-- filling in an outer unification variable.+-- See See Note [Tracking Given equalities]+updateGivenEqs tclvl ct inerts@(IC { inert_given_eq_lvl = ge_lvl })+ | not (isGivenCt ct) = inerts+ | not_equality ct = inerts -- See Note [Let-bound skolems]+ | otherwise = inerts { inert_given_eq_lvl = ge_lvl'+ , inert_given_eqs = True }+ where+ ge_lvl' | mentionsOuterVar tclvl (ctEvidence ct)+ -- Includes things like (c a), which *might* be an equality+ = tclvl+ | otherwise+ = ge_lvl++ not_equality :: Ct -> Bool+ -- True <=> definitely not an equality of any kind+ -- except for a let-bound skolem, which doesn't count+ -- See Note [Let-bound skolems]+ -- NB: no need to spot the boxed CDictCan (a ~ b) because its+ -- superclass (a ~# b) will be a CEqCan+ not_equality (CEqCan { cc_lhs = TyVarLHS tv }) = not (isOuterTyVar tclvl tv)+ not_equality (CDictCan {}) = True+ not_equality _ = False++-----------------------------------------+kickOutRewritable :: CtFlavourRole -- Flavour/role of the equality that+ -- is being added to the inert set+ -> CanEqLHS -- The new equality is lhs ~ ty+ -> InertCans+ -> TcS (Int, InertCans)+kickOutRewritable new_fr new_lhs ics+ = do { let (kicked_out, ics') = kick_out_rewritable new_fr new_lhs ics+ n_kicked = workListSize kicked_out++ ; unless (n_kicked == 0) $+ do { updWorkListTcS (appendWorkList kicked_out)++ -- The famapp-cache contains Given evidence from the inert set.+ -- If we're kicking out Givens, we need to remove this evidence+ -- from the cache, too.+ ; let kicked_given_ev_vars =+ [ ev_var | ct <- wl_eqs kicked_out+ , CtGiven { ctev_evar = ev_var } <- [ctEvidence ct] ]+ ; when (new_fr `eqCanRewriteFR` (Given, NomEq) &&+ -- if this isn't true, no use looking through the constraints+ not (null kicked_given_ev_vars)) $+ do { traceTcS "Given(s) have been kicked out; drop from famapp-cache"+ (ppr kicked_given_ev_vars)+ ; dropFromFamAppCache (mkVarSet kicked_given_ev_vars) }++ ; csTraceTcS $+ hang (text "Kick out, lhs =" <+> ppr new_lhs)+ 2 (vcat [ text "n-kicked =" <+> int n_kicked+ , text "kicked_out =" <+> ppr kicked_out+ , text "Residual inerts =" <+> ppr ics' ]) }++ ; return (n_kicked, ics') }++kick_out_rewritable :: CtFlavourRole -- Flavour/role of the equality that+ -- is being added to the inert set+ -> CanEqLHS -- The new equality is lhs ~ ty+ -> InertCans+ -> (WorkList, InertCans)+-- See Note [kickOutRewritable]+kick_out_rewritable new_fr new_lhs+ ics@(IC { inert_eqs = tv_eqs+ , inert_dicts = dictmap+ , inert_funeqs = funeqmap+ , inert_irreds = irreds+ , inert_insts = old_insts })+ | not (new_fr `eqMayRewriteFR` new_fr)+ = (emptyWorkList, ics)+ -- If new_fr can't rewrite itself, it can't rewrite+ -- anything else, so no need to kick out anything.+ -- (This is a common case: wanteds can't rewrite wanteds)+ -- Lemma (L2) in Note [Extending the inert equalities]++ | otherwise+ = (kicked_out, inert_cans_in)+ where+ -- inert_safehask stays unchanged; is that right?+ inert_cans_in = ics { inert_eqs = tv_eqs_in+ , inert_dicts = dicts_in+ , inert_funeqs = feqs_in+ , inert_irreds = irs_in+ , inert_insts = insts_in }++ kicked_out :: WorkList+ -- NB: use extendWorkList to ensure that kicked-out equalities get priority+ -- See Note [Prioritise equalities] (Kick-out).+ -- The irreds may include non-canonical (hetero-kinded) equality+ -- constraints, which perhaps may have become soluble after new_lhs+ -- is substituted; ditto the dictionaries, which may include (a~b)+ -- or (a~~b) constraints.+ kicked_out = foldr extendWorkListCt+ (emptyWorkList { wl_eqs = tv_eqs_out ++ feqs_out })+ ((dicts_out `andCts` irs_out)+ `extendCtsList` insts_out)++ (tv_eqs_out, tv_eqs_in) = foldDVarEnv (kick_out_eqs extend_tv_eqs)+ ([], emptyDVarEnv) tv_eqs+ (feqs_out, feqs_in) = foldFunEqs (kick_out_eqs extend_fun_eqs)+ funeqmap ([], emptyFunEqs)+ (dicts_out, dicts_in) = partitionDicts kick_out_ct dictmap+ (irs_out, irs_in) = partitionBag kick_out_ct irreds+ -- Kick out even insolubles: See Note [Rewrite insolubles]+ -- Of course we must kick out irreducibles like (c a), in case+ -- we can rewrite 'c' to something more useful++ -- Kick-out for inert instances+ -- See Note [Quantified constraints] in GHC.Tc.Solver.Canonical+ insts_out :: [Ct]+ insts_in :: [QCInst]+ (insts_out, insts_in)+ | fr_may_rewrite (Given, NomEq) -- All the insts are Givens+ = partitionWith kick_out_qci old_insts+ | otherwise+ = ([], old_insts)+ kick_out_qci qci+ | let ev = qci_ev qci+ , fr_can_rewrite_ty NomEq (ctEvPred (qci_ev qci))+ = Left (mkNonCanonical ev)+ | otherwise+ = Right qci++ (_, new_role) = new_fr++ fr_tv_can_rewrite_ty :: TyVar -> EqRel -> Type -> Bool+ fr_tv_can_rewrite_ty new_tv role ty+ = anyRewritableTyVar True role can_rewrite ty+ -- True: ignore casts and coercions+ where+ can_rewrite :: EqRel -> TyVar -> Bool+ can_rewrite old_role tv = new_role `eqCanRewrite` old_role && tv == new_tv++ fr_tf_can_rewrite_ty :: TyCon -> [TcType] -> EqRel -> Type -> Bool+ fr_tf_can_rewrite_ty new_tf new_tf_args role ty+ = anyRewritableTyFamApp role can_rewrite ty+ where+ can_rewrite :: EqRel -> TyCon -> [TcType] -> Bool+ can_rewrite old_role old_tf old_tf_args+ = new_role `eqCanRewrite` old_role &&+ tcEqTyConApps new_tf new_tf_args old_tf old_tf_args+ -- it's possible for old_tf_args to have too many. This is fine;+ -- we'll only check what we need to.++ {-# INLINE fr_can_rewrite_ty #-} -- perform the check here only once+ fr_can_rewrite_ty :: EqRel -> Type -> Bool+ fr_can_rewrite_ty = case new_lhs of+ TyVarLHS new_tv -> fr_tv_can_rewrite_ty new_tv+ TyFamLHS new_tf new_tf_args -> fr_tf_can_rewrite_ty new_tf new_tf_args++ fr_may_rewrite :: CtFlavourRole -> Bool+ fr_may_rewrite fs = new_fr `eqMayRewriteFR` fs+ -- Can the new item rewrite the inert item?++ {-# INLINE kick_out_ct #-} -- perform case on new_lhs here only once+ kick_out_ct :: Ct -> Bool+ -- Kick it out if the new CEqCan can rewrite the inert one+ -- See Note [kickOutRewritable]+ kick_out_ct = case new_lhs of+ TyVarLHS new_tv -> \ct -> let fs@(_,role) = ctFlavourRole ct in+ fr_may_rewrite fs+ && fr_tv_can_rewrite_ty new_tv role (ctPred ct)+ TyFamLHS new_tf new_tf_args+ -> \ct -> let fs@(_, role) = ctFlavourRole ct in+ fr_may_rewrite fs+ && fr_tf_can_rewrite_ty new_tf new_tf_args role (ctPred ct)++ extend_tv_eqs :: InertEqs -> CanEqLHS -> EqualCtList -> InertEqs+ extend_tv_eqs eqs (TyVarLHS tv) cts = extendDVarEnv eqs tv cts+ extend_tv_eqs eqs other _cts = pprPanic "extend_tv_eqs" (ppr eqs $$ ppr other)++ extend_fun_eqs :: FunEqMap EqualCtList -> CanEqLHS -> EqualCtList+ -> FunEqMap EqualCtList+ extend_fun_eqs eqs (TyFamLHS fam_tc fam_args) cts+ = insertTcApp eqs fam_tc fam_args cts+ extend_fun_eqs eqs other _cts = pprPanic "extend_fun_eqs" (ppr eqs $$ ppr other)++ kick_out_eqs :: (container -> CanEqLHS -> EqualCtList -> container)+ -> EqualCtList -> ([Ct], container)+ -> ([Ct], container)+ kick_out_eqs extend eqs (acc_out, acc_in)+ = (eqs_out `chkAppend` acc_out, case listToEqualCtList eqs_in of+ Nothing -> acc_in+ Just eqs_in_ecl@(EqualCtList (eq1 :| _))+ -> extend acc_in (cc_lhs eq1) eqs_in_ecl)+ where+ (eqs_out, eqs_in) = partition kick_out_eq (equalCtListToList eqs)++ -- Implements criteria K1-K3 in Note [Extending the inert equalities]+ kick_out_eq (CEqCan { cc_lhs = lhs, cc_rhs = rhs_ty+ , cc_ev = ev, cc_eq_rel = eq_rel })+ | not (fr_may_rewrite fs)+ = False -- Keep it in the inert set if the new thing can't rewrite it++ -- Below here (fr_may_rewrite fs) is True+ | fr_can_rewrite_ty eq_rel (canEqLHSType lhs) = True -- (K1)+ -- The above check redundantly checks the role & flavour,+ -- but it's very convenient++ | kick_out_for_inertness = True+ | kick_out_for_completeness = True+ | otherwise = False++ where+ fs = (ctEvFlavour ev, eq_rel)+ kick_out_for_inertness+ = (fs `eqMayRewriteFR` fs) -- (K2a)+ && not (fs `eqMayRewriteFR` new_fr) -- (K2b)+ && fr_can_rewrite_ty eq_rel rhs_ty -- (K2d)+ -- (K2c) is guaranteed by the first guard of keep_eq++ kick_out_for_completeness -- (K3) and Note [K3: completeness of solving]+ = case eq_rel of+ NomEq -> rhs_ty `eqType` canEqLHSType new_lhs -- (K3a)+ ReprEq -> is_can_eq_lhs_head new_lhs rhs_ty -- (K3b)++ kick_out_eq ct = pprPanic "keep_eq" (ppr ct)++ is_can_eq_lhs_head (TyVarLHS tv) = go+ where+ go (Rep.TyVarTy tv') = tv == tv'+ go (Rep.AppTy fun _) = go fun+ go (Rep.CastTy ty _) = go ty+ go (Rep.TyConApp {}) = False+ go (Rep.LitTy {}) = False+ go (Rep.ForAllTy {}) = False+ go (Rep.FunTy {}) = False+ go (Rep.CoercionTy {}) = False+ is_can_eq_lhs_head (TyFamLHS fun_tc fun_args) = go+ where+ go (Rep.TyVarTy {}) = False+ go (Rep.AppTy {}) = False -- no TyConApp to the left of an AppTy+ go (Rep.CastTy ty _) = go ty+ go (Rep.TyConApp tc args) = tcEqTyConApps fun_tc fun_args tc args+ go (Rep.LitTy {}) = False+ go (Rep.ForAllTy {}) = False+ go (Rep.FunTy {}) = False+ go (Rep.CoercionTy {}) = False++kickOutAfterUnification :: TcTyVar -> TcS Int+kickOutAfterUnification new_tv+ = do { ics <- getInertCans+ ; (n_kicked, ics2) <- kickOutRewritable (Given,NomEq)+ (TyVarLHS new_tv) ics+ -- Given because the tv := xi is given; NomEq because+ -- only nominal equalities are solved by unification++ ; setInertCans ics2+ ; return n_kicked }++-- See Wrinkle (2) in Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Canonical+kickOutAfterFillingCoercionHole :: CoercionHole -> Coercion -> TcS ()+kickOutAfterFillingCoercionHole hole filled_co+ = do { ics <- getInertCans+ ; let (kicked_out, ics') = kick_out ics+ n_kicked = workListSize kicked_out++ ; unless (n_kicked == 0) $+ do { updWorkListTcS (appendWorkList kicked_out)+ ; csTraceTcS $+ hang (text "Kick out, hole =" <+> ppr hole)+ 2 (vcat [ text "n-kicked =" <+> int n_kicked+ , text "kicked_out =" <+> ppr kicked_out+ , text "Residual inerts =" <+> ppr ics' ]) }++ ; setInertCans ics' }+ where+ holes_of_co = coercionHolesOfCo filled_co++ kick_out :: InertCans -> (WorkList, InertCans)+ kick_out ics@(IC { inert_irreds = irreds })+ = let (to_kick, to_keep) = partitionBagWith kick_ct irreds++ kicked_out = extendWorkListCts (bagToList to_kick) emptyWorkList+ ics' = ics { inert_irreds = to_keep }+ in+ (kicked_out, ics')++ kick_ct :: Ct -> Either Ct Ct+ -- Left: kick out; Right: keep. But even if we keep, we may need+ -- to update the set of blocking holes+ kick_ct ct@(CIrredCan { cc_status = BlockedCIS holes })+ | hole `elementOfUniqSet` holes+ = let new_holes = holes `delOneFromUniqSet` hole+ `unionUniqSets` holes_of_co+ updated_ct = ct { cc_status = BlockedCIS new_holes }+ in+ if isEmptyUniqSet new_holes+ then Left updated_ct+ else Right updated_ct+ kick_ct other = Right other++{- Note [kickOutRewritable]+~~~~~~~~~~~~~~~~~~~~~~~~~~~+See also Note [inert_eqs: the inert equalities].++When we add a new inert equality (lhs ~N ty) to the inert set,+we must kick out any inert items that could be rewritten by the+new equality, to maintain the inert-set invariants.++ - We want to kick out an existing inert constraint if+ a) the new constraint can rewrite the inert one+ b) 'lhs' is free in the inert constraint (so that it *will*)+ rewrite it if we kick it out.++ For (b) we use anyRewritableCanLHS, which examines the types /and+ kinds/ that are directly visible in the type. Hence+ we will have exposed all the rewriting we care about to make the+ most precise kinds visible for matching classes etc. No need to+ kick out constraints that mention type variables whose kinds+ contain this LHS!++ - A Derived equality can kick out [D] constraints in inert_eqs,+ inert_dicts, inert_irreds etc.++ - We don't kick out constraints from inert_solved_dicts, and+ inert_solved_funeqs optimistically. But when we lookup we have to+ take the substitution into account+++Note [Rewrite insolubles]+~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we have an insoluble alpha ~ [alpha], which is insoluble+because an occurs check. And then we unify alpha := [Int]. Then we+really want to rewrite the insoluble to [Int] ~ [[Int]]. Now it can+be decomposed. Otherwise we end up with a "Can't match [Int] ~+[[Int]]" which is true, but a bit confusing because the outer type+constructors match.++Hence:+ * In the main simplifier loops in GHC.Tc.Solver (solveWanteds,+ simpl_loop), we feed the insolubles in solveSimpleWanteds,+ so that they get rewritten (albeit not solved).++ * We kick insolubles out of the inert set, if they can be+ rewritten (see GHC.Tc.Solver.Monad.kick_out_rewritable)++ * We rewrite those insolubles in GHC.Tc.Solver.Canonical.+ See Note [Make sure that insolubles are fully rewritten]+-}++++--------------+addInertSafehask :: InertCans -> Ct -> InertCans+addInertSafehask ics item@(CDictCan { cc_class = cls, cc_tyargs = tys })+ = ics { inert_safehask = addDict (inert_dicts ics) cls tys item }++addInertSafehask _ item+ = pprPanic "addInertSafehask: can't happen! Inserting " $ ppr item++insertSafeOverlapFailureTcS :: InstanceWhat -> Ct -> TcS ()+-- See Note [Safe Haskell Overlapping Instances Implementation] in GHC.Tc.Solver+insertSafeOverlapFailureTcS what item+ | safeOverlap what = return ()+ | otherwise = updInertCans (\ics -> addInertSafehask ics item)++getSafeOverlapFailures :: TcS Cts+-- See Note [Safe Haskell Overlapping Instances Implementation] in GHC.Tc.Solver+getSafeOverlapFailures+ = do { IC { inert_safehask = safehask } <- getInertCans+ ; return $ foldDicts consCts safehask emptyCts }++--------------+addSolvedDict :: InstanceWhat -> CtEvidence -> Class -> [Type] -> TcS ()+-- Conditionally add a new item in the solved set of the monad+-- See Note [Solved dictionaries]+addSolvedDict what item cls tys+ | isWanted item+ , instanceReturnsDictCon what+ = do { traceTcS "updSolvedSetTcs:" $ ppr item+ ; updInertTcS $ \ ics ->+ ics { inert_solved_dicts = addDict (inert_solved_dicts ics) cls tys item } }+ | otherwise+ = return ()++getSolvedDicts :: TcS (DictMap CtEvidence)+getSolvedDicts = do { ics <- getTcSInerts; return (inert_solved_dicts ics) }++setSolvedDicts :: DictMap CtEvidence -> TcS ()+setSolvedDicts solved_dicts+ = updInertTcS $ \ ics ->+ ics { inert_solved_dicts = solved_dicts }+++{- *********************************************************************+* *+ Other inert-set operations+* *+********************************************************************* -}++updInertTcS :: (InertSet -> InertSet) -> TcS ()+-- Modify the inert set with the supplied function+updInertTcS upd_fn+ = do { is_var <- getTcSInertsRef+ ; wrapTcS (do { curr_inert <- TcM.readTcRef is_var+ ; TcM.writeTcRef is_var (upd_fn curr_inert) }) }++getInertCans :: TcS InertCans+getInertCans = do { inerts <- getTcSInerts; return (inert_cans inerts) }++setInertCans :: InertCans -> TcS ()+setInertCans ics = updInertTcS $ \ inerts -> inerts { inert_cans = ics }++updRetInertCans :: (InertCans -> (a, InertCans)) -> TcS a+-- Modify the inert set with the supplied function+updRetInertCans upd_fn+ = do { is_var <- getTcSInertsRef+ ; wrapTcS (do { inerts <- TcM.readTcRef is_var+ ; let (res, cans') = upd_fn (inert_cans inerts)+ ; TcM.writeTcRef is_var (inerts { inert_cans = cans' })+ ; return res }) }++updInertCans :: (InertCans -> InertCans) -> TcS ()+-- Modify the inert set with the supplied function+updInertCans upd_fn+ = updInertTcS $ \ inerts -> inerts { inert_cans = upd_fn (inert_cans inerts) }++updInertDicts :: (DictMap Ct -> DictMap Ct) -> TcS ()+-- Modify the inert set with the supplied function+updInertDicts upd_fn+ = updInertCans $ \ ics -> ics { inert_dicts = upd_fn (inert_dicts ics) }++updInertSafehask :: (DictMap Ct -> DictMap Ct) -> TcS ()+-- Modify the inert set with the supplied function+updInertSafehask upd_fn+ = updInertCans $ \ ics -> ics { inert_safehask = upd_fn (inert_safehask ics) }++updInertIrreds :: (Cts -> Cts) -> TcS ()+-- Modify the inert set with the supplied function+updInertIrreds upd_fn+ = updInertCans $ \ ics -> ics { inert_irreds = upd_fn (inert_irreds ics) }++getInertEqs :: TcS (DTyVarEnv EqualCtList)+getInertEqs = do { inert <- getInertCans; return (inert_eqs inert) }++getInnermostGivenEqLevel :: TcS TcLevel+getInnermostGivenEqLevel = do { inert <- getInertCans+ ; return (inert_given_eq_lvl inert) }++getInertInsols :: TcS Cts+-- Returns insoluble equality constraints+-- specifically including Givens+getInertInsols = do { inert <- getInertCans+ ; return (filterBag insolubleEqCt (inert_irreds inert)) }++getInertGivens :: TcS [Ct]+-- Returns the Given constraints in the inert set+getInertGivens+ = do { inerts <- getInertCans+ ; let all_cts = foldDicts (:) (inert_dicts inerts)+ $ foldFunEqs (\ecl out -> equalCtListToList ecl ++ out)+ (inert_funeqs inerts)+ $ concatMap equalCtListToList (dVarEnvElts (inert_eqs inerts))+ ; return (filter isGivenCt all_cts) }++getPendingGivenScs :: TcS [Ct]+-- Find all inert Given dictionaries, or quantified constraints,+-- whose cc_pend_sc flag is True+-- and that belong to the current level+-- Set their cc_pend_sc flag to False in the inert set, and return that Ct+getPendingGivenScs = do { lvl <- getTcLevel+ ; updRetInertCans (get_sc_pending lvl) }++get_sc_pending :: TcLevel -> InertCans -> ([Ct], InertCans)+get_sc_pending this_lvl ic@(IC { inert_dicts = dicts, inert_insts = insts })+ = ASSERT2( all isGivenCt sc_pending, ppr sc_pending )+ -- When getPendingScDics is called,+ -- there are never any Wanteds in the inert set+ (sc_pending, ic { inert_dicts = dicts', inert_insts = insts' })+ where+ sc_pending = sc_pend_insts ++ sc_pend_dicts++ sc_pend_dicts = foldDicts get_pending dicts []+ dicts' = foldr add dicts sc_pend_dicts++ (sc_pend_insts, insts') = mapAccumL get_pending_inst [] insts++ get_pending :: Ct -> [Ct] -> [Ct] -- Get dicts with cc_pend_sc = True+ -- but flipping the flag+ get_pending dict dicts+ | Just dict' <- isPendingScDict dict+ , belongs_to_this_level (ctEvidence dict)+ = dict' : dicts+ | otherwise+ = dicts++ add :: Ct -> DictMap Ct -> DictMap Ct+ add ct@(CDictCan { cc_class = cls, cc_tyargs = tys }) dicts+ = addDict dicts cls tys ct+ add ct _ = pprPanic "getPendingScDicts" (ppr ct)++ get_pending_inst :: [Ct] -> QCInst -> ([Ct], QCInst)+ get_pending_inst cts qci@(QCI { qci_ev = ev })+ | Just qci' <- isPendingScInst qci+ , belongs_to_this_level ev+ = (CQuantCan qci' : cts, qci')+ | otherwise+ = (cts, qci)++ belongs_to_this_level ev = ctLocLevel (ctEvLoc ev) == this_lvl+ -- We only want Givens from this level; see (3a) in+ -- Note [The superclass story] in GHC.Tc.Solver.Canonical++getUnsolvedInerts :: TcS ( Bag Implication+ , Cts ) -- All simple constraints+-- Return all the unsolved [Wanted] or [Derived] constraints+--+-- Post-condition: the returned simple constraints are all fully zonked+-- (because they come from the inert set)+-- the unsolved implics may not be+getUnsolvedInerts+ = do { IC { inert_eqs = tv_eqs+ , inert_funeqs = fun_eqs+ , inert_irreds = irreds+ , inert_dicts = idicts+ } <- getInertCans++ ; let unsolved_tv_eqs = foldTyEqs add_if_unsolved tv_eqs emptyCts+ unsolved_fun_eqs = foldFunEqs add_if_unsolveds fun_eqs emptyCts+ unsolved_irreds = Bag.filterBag is_unsolved irreds+ unsolved_dicts = foldDicts add_if_unsolved idicts emptyCts+ unsolved_others = unsolved_irreds `unionBags` unsolved_dicts++ ; implics <- getWorkListImplics++ ; traceTcS "getUnsolvedInerts" $+ vcat [ text " tv eqs =" <+> ppr unsolved_tv_eqs+ , text "fun eqs =" <+> ppr unsolved_fun_eqs+ , text "others =" <+> ppr unsolved_others+ , text "implics =" <+> ppr implics ]++ ; return ( implics, unsolved_tv_eqs `unionBags`+ unsolved_fun_eqs `unionBags`+ unsolved_others) }+ where+ add_if_unsolved :: Ct -> Cts -> Cts+ add_if_unsolved ct cts | is_unsolved ct = ct `consCts` cts+ | otherwise = cts++ add_if_unsolveds :: EqualCtList -> Cts -> Cts+ add_if_unsolveds new_cts old_cts = foldr add_if_unsolved old_cts+ (equalCtListToList new_cts)++ is_unsolved ct = not (isGivenCt ct) -- Wanted or Derived++getHasGivenEqs :: TcLevel -- TcLevel of this implication+ -> TcS ( HasGivenEqs -- are there Given equalities?+ , Cts ) -- Insoluble equalities arising from givens+-- See Note [Tracking Given equalities]+getHasGivenEqs tclvl+ = do { inerts@(IC { inert_irreds = irreds+ , inert_given_eqs = given_eqs+ , inert_given_eq_lvl = ge_lvl })+ <- getInertCans+ ; let insols = filterBag insolubleEqCt irreds+ -- Specifically includes ones that originated in some+ -- outer context but were refined to an insoluble by+ -- a local equality; so do /not/ add ct_given_here.++ -- See Note [HasGivenEqs] in GHC.Tc.Types.Constraint, and+ -- Note [Tracking Given equalities] in this module+ has_ge | ge_lvl == tclvl = MaybeGivenEqs+ | given_eqs = LocalGivenEqs+ | otherwise = NoGivenEqs++ ; traceTcS "getHasGivenEqs" $+ vcat [ text "given_eqs:" <+> ppr given_eqs+ , text "ge_lvl:" <+> ppr ge_lvl+ , text "ambient level:" <+> ppr tclvl+ , text "Inerts:" <+> ppr inerts+ , text "Insols:" <+> ppr insols]+ ; return (has_ge, insols) }++mentionsOuterVar :: TcLevel -> CtEvidence -> Bool+mentionsOuterVar tclvl ev+ = anyFreeVarsOfType (isOuterTyVar tclvl) $+ ctEvPred ev++isOuterTyVar :: TcLevel -> TyCoVar -> Bool+-- True of a type variable that comes from a+-- shallower level than the ambient level (tclvl)+isOuterTyVar tclvl tv+ | isTyVar tv = tclvl `strictlyDeeperThan` tcTyVarLevel tv+ || isPromotableMetaTyVar tv+ -- isPromotable: a meta-tv alpha[3] may end up unifying with skolem b[2],+ -- so treat it as an "outer" var, even at level 3.+ -- This will become redundant after fixing #18929.+ | otherwise = False -- Coercion variables; doesn't much matter++-- | Returns Given constraints that might,+-- potentially, match the given pred. This is used when checking to see if a+-- Given might overlap with an instance. See Note [Instance and Given overlap]+-- in "GHC.Tc.Solver.Interact"+matchableGivens :: CtLoc -> PredType -> InertSet -> Cts+matchableGivens loc_w pred_w (IS { inert_cans = inert_cans })+ = filterBag matchable_given all_relevant_givens+ where+ -- just look in class constraints and irreds. matchableGivens does get called+ -- for ~R constraints, but we don't need to look through equalities, because+ -- canonical equalities are used for rewriting. We'll only get caught by+ -- non-canonical -- that is, irreducible -- equalities.+ all_relevant_givens :: Cts+ all_relevant_givens+ | Just (clas, _) <- getClassPredTys_maybe pred_w+ = findDictsByClass (inert_dicts inert_cans) clas+ `unionBags` inert_irreds inert_cans+ | otherwise+ = inert_irreds inert_cans++ matchable_given :: Ct -> Bool+ matchable_given ct+ | CtGiven { ctev_loc = loc_g, ctev_pred = pred_g } <- ctEvidence ct+ = mightMatchLater pred_g loc_g pred_w loc_w++ | otherwise+ = False++mightMatchLater :: TcPredType -> CtLoc -> TcPredType -> CtLoc -> Bool+-- See Note [What might match later?]+mightMatchLater given_pred given_loc wanted_pred wanted_loc+ | prohibitedSuperClassSolve given_loc wanted_loc+ = False++ | SurelyApart <- tcUnifyTysFG bind_meta_tv [flattened_given] [flattened_wanted]+ = False++ | otherwise+ = True -- safe answer+ where+ in_scope = mkInScopeSet $ tyCoVarsOfTypes [given_pred, wanted_pred]++ -- NB: flatten both at the same time, so that we can share mappings+ -- from type family applications to variables, and also to guarantee+ -- that the fresh variables are really fresh between the given and+ -- the wanted.+ ([flattened_given, flattened_wanted], var_mapping)+ = flattenTysX in_scope [given_pred, wanted_pred]++ bind_meta_tv :: TcTyVar -> BindFlag+ -- Any meta tyvar may be unified later, so we treat it as+ -- bindable when unifying with givens. That ensures that we+ -- conservatively assume that a meta tyvar might get unified with+ -- something that matches the 'given', until demonstrated+ -- otherwise. More info in Note [Instance and Given overlap]+ -- in GHC.Tc.Solver.Interact+ bind_meta_tv tv | is_meta_tv tv = BindMe++ | Just (_fam_tc, fam_args) <- lookupVarEnv var_mapping tv+ , anyFreeVarsOfTypes is_meta_tv fam_args+ = BindMe++ | otherwise = Skolem++ -- CycleBreakerTvs really stands for a type family application in+ -- a given; these won't contain touchable meta-variables+ is_meta_tv = isMetaTyVar <&&> not . isCycleBreakerTyVar++prohibitedSuperClassSolve :: CtLoc -> CtLoc -> Bool+-- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance+prohibitedSuperClassSolve from_loc solve_loc+ | GivenOrigin (InstSC given_size) <- ctLocOrigin from_loc+ , ScOrigin wanted_size <- ctLocOrigin solve_loc+ = given_size >= wanted_size+ | otherwise+ = False++{- Note [Unsolved Derived equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In getUnsolvedInerts, we return a derived equality from the inert_eqs+because it is a candidate for floating out of this implication. We+only float equalities with a meta-tyvar on the left, so we only pull+those out here.++Note [What might match later?]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We must determine whether a Given might later match a Wanted. We+definitely need to account for the possibility that any metavariable+in the Wanted might be arbitrarily instantiated. We do *not* want+to allow skolems in the Given to be instantiated. But what about+type family applications? (Examples are below the explanation.)++To allow flexibility in how type family applications unify 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 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.++Examples:+ [G] C a+ [W] C alpha+ This easily might match later.++ [G] C a+ [W] C (F alpha)+ This might match later, too, but we need to flatten the (F alpha)+ to a fresh variable so that the unifier can connect the two.++ [G] C (F alpha)+ [W] C a+ This also might match later. Again, we will need to flatten to+ find this out. (Surprised about a metavariable in a Given? See+ #18929.)++ [G] C (F a)+ [W] C a+ This won't match later. We're not going to get new Givens that+ can inform the F a, and so this is a no-go.++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.+removeInertCts cts icans = foldl' removeInertCt icans cts++removeInertCt :: InertCans -> Ct -> InertCans+removeInertCt is ct =+ case ct of++ CDictCan { cc_class = cl, cc_tyargs = tys } ->+ is { inert_dicts = delDict (inert_dicts is) cl tys }++ CEqCan { cc_lhs = lhs, cc_rhs = rhs } -> delEq is lhs rhs++ CQuantCan {} -> panic "removeInertCt: CQuantCan"+ CIrredCan {} -> panic "removeInertCt: CIrredEvCan"+ CNonCanonical {} -> panic "removeInertCt: CNonCanonical"++-- | Looks up a family application in the inerts; returned coercion+-- is oriented input ~ output+lookupFamAppInert :: TyCon -> [Type] -> TcS (Maybe (TcCoercion, TcType, CtFlavourRole))+lookupFamAppInert fam_tc tys+ = do { IS { inert_cans = IC { inert_funeqs = inert_funeqs } } <- getTcSInerts+ ; return (lookup_inerts inert_funeqs) }+ where+ lookup_inerts inert_funeqs+ | Just (EqualCtList (CEqCan { cc_ev = ctev, cc_rhs = rhs } :| _))+ <- findFunEq inert_funeqs fam_tc tys+ = Just (ctEvCoercion ctev, rhs, ctEvFlavourRole ctev)+ | otherwise = Nothing++lookupInInerts :: CtLoc -> TcPredType -> TcS (Maybe CtEvidence)+-- Is this exact predicate type cached in the solved or canonicals of the InertSet?+lookupInInerts loc pty+ | ClassPred cls tys <- classifyPredType pty+ = do { inerts <- getTcSInerts+ ; return (lookupSolvedDict inerts loc cls tys `mplus`+ lookupInertDict (inert_cans inerts) loc cls tys) }+ | otherwise -- NB: No caching for equalities, IPs, holes, or errors+ = return Nothing++-- | Look up a dictionary inert.+lookupInertDict :: InertCans -> CtLoc -> Class -> [Type] -> Maybe CtEvidence+lookupInertDict (IC { inert_dicts = dicts }) loc cls tys+ = case findDict dicts loc cls tys of+ Just ct -> Just (ctEvidence ct)+ _ -> Nothing++-- | Look up a solved inert.+lookupSolvedDict :: InertSet -> CtLoc -> Class -> [Type] -> Maybe CtEvidence+-- Returns just if exactly this predicate type exists in the solved.+lookupSolvedDict (IS { inert_solved_dicts = solved }) loc cls tys+ = case findDict solved loc cls tys of+ Just ev -> Just ev+ _ -> Nothing++---------------------------+lookupFamAppCache :: TyCon -> [Type] -> TcS (Maybe (TcCoercion, TcType))+lookupFamAppCache fam_tc tys+ = do { IS { inert_famapp_cache = famapp_cache } <- getTcSInerts+ ; case findFunEq famapp_cache fam_tc tys of+ result@(Just (co, ty)) ->+ do { traceTcS "famapp_cache hit" (vcat [ ppr (mkTyConApp fam_tc tys)+ , ppr ty+ , ppr co ])+ ; return result }+ Nothing -> return Nothing }++extendFamAppCache :: TyCon -> [Type] -> (TcCoercion, TcType) -> TcS ()+-- NB: co :: rhs ~ F tys, to match expectations of rewriter+extendFamAppCache tc xi_args stuff@(_, ty)+ = do { dflags <- getDynFlags+ ; when (gopt Opt_FamAppCache dflags) $+ do { traceTcS "extendFamAppCache" (vcat [ ppr tc <+> ppr xi_args+ , ppr ty ])+ -- 'co' can be bottom, in the case of derived items+ ; updInertTcS $ \ is@(IS { inert_famapp_cache = fc }) ->+ is { inert_famapp_cache = insertFunEq fc tc xi_args stuff } } }++-- Remove entries from the cache whose evidence mentions variables in the+-- supplied set+dropFromFamAppCache :: VarSet -> TcS ()+dropFromFamAppCache varset+ = do { inerts@(IS { inert_famapp_cache = famapp_cache }) <- getTcSInerts+ ; let filtered = filterTcAppMap check famapp_cache+ ; setTcSInerts $ inerts { inert_famapp_cache = filtered } }+ where+ check :: (TcCoercion, TcType) -> Bool+ check (co, _) = not (anyFreeVarsOfCo (`elemVarSet` varset) co)++{- *********************************************************************+* *+ Irreds+* *+********************************************************************* -}++foldIrreds :: (Ct -> b -> b) -> Cts -> b -> b+foldIrreds k irreds z = foldr k z irreds+++{- *********************************************************************+* *+ TcAppMap+* *+************************************************************************++Note [Use loose types in inert set]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Whenever we are looking up an inert dictionary (CDictCan) or function+equality (CEqCan), we use a TcAppMap, which uses the Unique of the+class/type family tycon and then a trie which maps the arguments. This+trie does *not* need to match the kinds of the arguments; this Note+explains why.++Consider the types ty0 = (T ty1 ty2 ty3 ty4) and ty0' = (T ty1' ty2' ty3' ty4'),+where ty4 and ty4' have different kinds. Let's further assume that both types+ty0 and ty0' are well-typed. Because the kind of T is closed, it must be that+one of the ty1..ty3 does not match ty1'..ty3' (and that the kind of the fourth+argument to T is dependent on whichever one changed). Since we are matching+all arguments, during the inert-set lookup, we know that ty1..ty3 do indeed+match ty1'..ty3'. Therefore, the kind of ty4 and ty4' must match, too --+without ever looking at it.++Accordingly, we use LooseTypeMap, which skips the kind check when looking+up a type. I (Richard E) believe this is just an optimization, and that+looking at kinds would be harmless.++-}++type TcAppMap a = DTyConEnv (ListMap LooseTypeMap a)+ -- Indexed by tycon then the arg types, using "loose" matching, where+ -- we don't require kind equality. This allows, for example, (a |> co)+ -- to match (a).+ -- See Note [Use loose types in inert set]+ -- Used for types and classes; hence UniqDFM+ -- See Note [foldTM determinism] in GHC.Data.TrieMap for why we use DTyConEnv here++isEmptyTcAppMap :: TcAppMap a -> Bool+isEmptyTcAppMap m = isEmptyDTyConEnv m++emptyTcAppMap :: TcAppMap a+emptyTcAppMap = emptyDTyConEnv++findTcApp :: TcAppMap a -> TyCon -> [Type] -> Maybe a+findTcApp m tc tys = do { tys_map <- lookupDTyConEnv m tc+ ; lookupTM tys tys_map }++delTcApp :: TcAppMap a -> TyCon -> [Type] -> TcAppMap a+delTcApp m tc tys = adjustDTyConEnv (deleteTM tys) m tc++insertTcApp :: TcAppMap a -> TyCon -> [Type] -> a -> TcAppMap a+insertTcApp m tc tys ct = alterDTyConEnv alter_tm m tc+ where+ alter_tm mb_tm = Just (insertTM tys ct (mb_tm `orElse` emptyTM))++alterTcApp :: forall a. TcAppMap a -> TyCon -> [Type] -> (Maybe a -> Maybe a) -> TcAppMap a+alterTcApp m tc tys upd = alterDTyConEnv alter_tm m tc+ where+ alter_tm :: Maybe (ListMap LooseTypeMap a) -> Maybe (ListMap LooseTypeMap a)+ alter_tm m_elt = Just (alterTM tys upd (m_elt `orElse` emptyTM))++filterTcAppMap :: forall a. (a -> Bool) -> TcAppMap a -> TcAppMap a+filterTcAppMap f m = mapMaybeDTyConEnv one_tycon m+ where+ one_tycon :: ListMap LooseTypeMap a -> Maybe (ListMap LooseTypeMap a)+ one_tycon tm+ | isEmptyTM filtered_tm = Nothing+ | otherwise = Just filtered_tm+ where+ filtered_tm = filterTM f tm++tcAppMapToBag :: TcAppMap a -> Bag a+tcAppMapToBag m = foldTcAppMap consBag m emptyBag++foldTcAppMap :: (a -> b -> b) -> TcAppMap a -> b -> b+foldTcAppMap k m z = foldDTyConEnv (foldTM k) z m+++{- *********************************************************************+* *+ DictMap+* *+********************************************************************* -}+++{- Note [Tuples hiding implicit parameters]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider+ f,g :: (?x::Int, C a) => a -> a+ f v = let ?x = 4 in g v++The call to 'g' gives rise to a Wanted constraint (?x::Int, C a).+We must /not/ solve this from the Given (?x::Int, C a), because of+the intervening binding for (?x::Int). #14218.++We deal with this by arranging that we always fail when looking up a+tuple constraint that hides an implicit parameter. Not that this applies+ * both to the inert_dicts (lookupInertDict)+ * and to the solved_dicts (looukpSolvedDict)+An alternative would be not to extend these sets with such tuple+constraints, but it seemed more direct to deal with the lookup.++Note [Solving CallStack constraints]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose f :: HasCallStack => blah. Then++* Each call to 'f' gives rise to+ [W] s1 :: IP "callStack" CallStack -- CtOrigin = OccurrenceOf f+ with a CtOrigin that says "OccurrenceOf f".+ Remember that HasCallStack is just shorthand for+ IP "callStack CallStack+ See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence++* We cannonicalise such constraints, in GHC.Tc.Solver.Canonical.canClassNC, by+ pushing the call-site info on the stack, and changing the CtOrigin+ to record that has been done.+ Bind: s1 = pushCallStack <site-info> s2+ [W] s2 :: IP "callStack" CallStack -- CtOrigin = IPOccOrigin++* Then, and only then, we can solve the constraint from an enclosing+ Given.++So we must be careful /not/ to solve 's1' from the Givens. Again,+we ensure this by arranging that findDict always misses when looking+up souch constraints.+-}++type DictMap a = TcAppMap a++emptyDictMap :: DictMap a+emptyDictMap = emptyTcAppMap++findDict :: DictMap a -> CtLoc -> Class -> [Type] -> Maybe a+findDict m loc cls tys+ | hasIPSuperClasses cls tys -- See Note [Tuples hiding implicit parameters]+ = Nothing++ | Just {} <- isCallStackPred cls tys+ , OccurrenceOf {} <- ctLocOrigin loc+ = Nothing -- See Note [Solving CallStack constraints]++ | otherwise+ = findTcApp m (classTyCon cls) tys++findDictsByClass :: DictMap a -> Class -> Bag a+findDictsByClass m cls+ | Just tm <- lookupDTyConEnv m (classTyCon cls) = foldTM consBag tm emptyBag+ | otherwise = emptyBag++delDict :: DictMap a -> Class -> [Type] -> DictMap a+delDict m cls tys = delTcApp m (classTyCon cls) tys++addDict :: DictMap a -> Class -> [Type] -> a -> DictMap a+addDict m cls tys item = insertTcApp m (classTyCon cls) tys item++addDictsByClass :: DictMap Ct -> Class -> Bag Ct -> DictMap Ct+addDictsByClass m cls items+ = extendDTyConEnv m (classTyCon cls) (foldr add emptyTM items)+ where+ add ct@(CDictCan { cc_tyargs = tys }) tm = insertTM tys ct tm+ add ct _ = pprPanic "addDictsByClass" (ppr ct)++filterDicts :: (Ct -> Bool) -> DictMap Ct -> DictMap Ct+filterDicts f m = filterTcAppMap f m++partitionDicts :: (Ct -> Bool) -> DictMap Ct -> (Bag Ct, DictMap Ct)+partitionDicts f m = foldTcAppMap k m (emptyBag, emptyDicts)+ where+ k ct (yeses, noes) | f ct = (ct `consBag` yeses, noes)+ | otherwise = (yeses, add ct noes)+ add ct@(CDictCan { cc_class = cls, cc_tyargs = tys }) m+ = addDict m cls tys ct+ add ct _ = pprPanic "partitionDicts" (ppr ct)++dictsToBag :: DictMap a -> Bag a+dictsToBag = tcAppMapToBag++foldDicts :: (a -> b -> b) -> DictMap a -> b -> b+foldDicts = foldTcAppMap++emptyDicts :: DictMap a+emptyDicts = emptyTcAppMap+++{- *********************************************************************+* *+ FunEqMap+* *+********************************************************************* -}++type FunEqMap a = TcAppMap a -- A map whose key is a (TyCon, [Type]) pair++emptyFunEqs :: TcAppMap a+emptyFunEqs = emptyTcAppMap++findFunEq :: FunEqMap a -> TyCon -> [Type] -> Maybe a+findFunEq m tc tys = findTcApp m tc tys++findFunEqsByTyCon :: FunEqMap a -> TyCon -> [a]+-- Get inert function equation constraints that have the given tycon+-- in their head. Not that the constraints remain in the inert set.+-- We use this to check for derived interactions with built-in type-function+-- constructors.+findFunEqsByTyCon m tc+ | Just tm <- lookupDTyConEnv m tc = foldTM (:) tm []+ | otherwise = []++foldFunEqs :: (a -> b -> b) -> FunEqMap a -> b -> b+foldFunEqs = foldTcAppMap++insertFunEq :: FunEqMap a -> TyCon -> [Type] -> a -> FunEqMap a+insertFunEq m tc tys val = insertTcApp m tc tys val++{-+************************************************************************+* *+* The TcS solver monad *+* *+************************************************************************++Note [The TcS monad]+~~~~~~~~~~~~~~~~~~~~+The TcS monad is a weak form of the main Tc monad++All you can do is+ * fail+ * allocate new variables+ * fill in evidence variables++Filling in a dictionary evidence variable means to create a binding+for it, so TcS carries a mutable location where the binding can be+added. This is initialised from the innermost implication constraint.+-}++data TcSEnv+ = TcSEnv {+ tcs_ev_binds :: EvBindsVar,++ tcs_unified :: IORef Int,+ -- The number of unification variables we have filled+ -- The important thing is whether it is non-zero++ tcs_unif_lvl :: IORef (Maybe TcLevel),+ -- The Unification Level Flag+ -- Outermost level at which we have unified a meta tyvar+ -- Starts at Nothing, then (Just i), then (Just j) where j<i+ -- See Note [The Unification Level Flag]++ tcs_count :: IORef Int, -- Global step count++ tcs_inerts :: IORef InertSet, -- Current inert set++ -- See Note [WorkList priorities] and+ tcs_worklist :: IORef WorkList -- Current worklist+ }++---------------+newtype TcS a = TcS { unTcS :: TcSEnv -> TcM a } deriving (Functor)++instance Applicative TcS where+ pure x = TcS (\_ -> return x)+ (<*>) = ap++instance Monad TcS where+ m >>= k = TcS (\ebs -> unTcS m ebs >>= \r -> unTcS (k r) ebs)++instance MonadFail TcS where+ fail err = TcS (\_ -> fail err)++instance MonadUnique TcS where+ getUniqueSupplyM = wrapTcS getUniqueSupplyM++instance HasModule TcS where+ getModule = wrapTcS getModule++instance MonadThings TcS where+ lookupThing n = wrapTcS (lookupThing n)++-- Basic functionality+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+wrapTcS :: TcM a -> TcS a+-- Do not export wrapTcS, because it promotes an arbitrary TcM to TcS,+-- and TcS is supposed to have limited functionality+wrapTcS = TcS . const -- a TcM action will not use the TcEvBinds++wrapErrTcS :: TcM a -> TcS a+-- The thing wrapped should just fail+-- There's no static check; it's up to the user+-- Having a variant for each error message is too painful+wrapErrTcS = wrapTcS++wrapWarnTcS :: TcM a -> TcS a+-- The thing wrapped should just add a warning, or no-op+-- There's no static check; it's up to the user+wrapWarnTcS = wrapTcS++failTcS, panicTcS :: SDoc -> TcS a+warnTcS :: WarningFlag -> SDoc -> TcS ()+addErrTcS :: SDoc -> TcS ()+failTcS = wrapTcS . TcM.failWith+warnTcS flag = wrapTcS . TcM.addWarn (Reason flag)+addErrTcS = wrapTcS . TcM.addErr+panicTcS doc = pprPanic "GHC.Tc.Solver.Canonical" doc++traceTcS :: String -> SDoc -> TcS ()+traceTcS herald doc = wrapTcS (TcM.traceTc herald doc)+{-# INLINE traceTcS #-} -- see Note [INLINE conditional tracing utilities]++runTcPluginTcS :: TcPluginM a -> TcS a+runTcPluginTcS m = wrapTcS . runTcPluginM m =<< getTcEvBindsVar++instance HasDynFlags TcS where+ getDynFlags = wrapTcS getDynFlags++getGlobalRdrEnvTcS :: TcS GlobalRdrEnv+getGlobalRdrEnvTcS = wrapTcS TcM.getGlobalRdrEnv++bumpStepCountTcS :: TcS ()+bumpStepCountTcS = TcS $ \env -> do { let ref = tcs_count env+ ; n <- TcM.readTcRef ref+ ; TcM.writeTcRef ref (n+1) }++csTraceTcS :: SDoc -> TcS ()+csTraceTcS doc+ = wrapTcS $ csTraceTcM (return doc)+{-# INLINE csTraceTcS #-} -- see Note [INLINE conditional tracing utilities]++traceFireTcS :: CtEvidence -> SDoc -> TcS ()+-- Dump a rule-firing trace+traceFireTcS ev doc+ = TcS $ \env -> csTraceTcM $+ do { n <- TcM.readTcRef (tcs_count env)+ ; tclvl <- TcM.getTcLevel+ ; return (hang (text "Step" <+> int n+ <> brackets (text "l:" <> ppr tclvl <> comma <>+ text "d:" <> ppr (ctLocDepth (ctEvLoc ev)))+ <+> doc <> colon)+ 4 (ppr ev)) }+{-# INLINE traceFireTcS #-} -- see Note [INLINE conditional tracing utilities]++csTraceTcM :: TcM SDoc -> TcM ()+-- Constraint-solver tracing, -ddump-cs-trace+csTraceTcM mk_doc+ = do { dflags <- getDynFlags+ ; when ( dopt Opt_D_dump_cs_trace dflags+ || dopt Opt_D_dump_tc_trace dflags )+ ( do { msg <- mk_doc+ ; TcM.dumpTcRn False+ (dumpOptionsFromFlag Opt_D_dump_cs_trace)+ "" FormatText+ msg }) }+{-# INLINE csTraceTcM #-} -- see Note [INLINE conditional tracing utilities]++runTcS :: TcS a -- What to run+ -> TcM (a, EvBindMap)+runTcS tcs+ = do { ev_binds_var <- TcM.newTcEvBinds+ ; res <- runTcSWithEvBinds ev_binds_var tcs+ ; ev_binds <- TcM.getTcEvBindsMap ev_binds_var+ ; return (res, ev_binds) }+-- | This variant of 'runTcS' will keep solving, even when only Deriveds+-- are left around. It also doesn't return any evidence, as callers won't+-- need it.+runTcSDeriveds :: TcS a -> TcM a+runTcSDeriveds tcs+ = do { ev_binds_var <- TcM.newTcEvBinds+ ; runTcSWithEvBinds ev_binds_var tcs }++-- | This can deal only with equality constraints.+runTcSEqualities :: TcS a -> TcM a+runTcSEqualities thing_inside+ = do { ev_binds_var <- TcM.newNoTcEvBinds+ ; runTcSWithEvBinds ev_binds_var thing_inside }++-- | A variant of 'runTcS' that takes and returns an 'InertSet' for+-- later resumption of the 'TcS' session.+runTcSInerts :: InertSet -> TcS a -> TcM (a, InertSet)+runTcSInerts inerts tcs = do+ ev_binds_var <- TcM.newTcEvBinds+ runTcSWithEvBinds' False ev_binds_var $ do+ setTcSInerts inerts+ a <- tcs+ new_inerts <- getTcSInerts+ return (a, new_inerts)++runTcSWithEvBinds :: EvBindsVar+ -> TcS a+ -> TcM a+runTcSWithEvBinds = runTcSWithEvBinds' True++runTcSWithEvBinds' :: Bool -- ^ Restore type variable cycles afterwards?+ -- Don't if you want to reuse the InertSet.+ -- See also Note [Type variable cycles in Givens]+ -- in GHC.Tc.Solver.Canonical+ -> EvBindsVar+ -> TcS a+ -> TcM a+runTcSWithEvBinds' restore_cycles ev_binds_var tcs+ = do { unified_var <- TcM.newTcRef 0+ ; step_count <- TcM.newTcRef 0+ ; inert_var <- TcM.newTcRef emptyInert+ ; wl_var <- TcM.newTcRef emptyWorkList+ ; unif_lvl_var <- TcM.newTcRef Nothing+ ; let env = TcSEnv { tcs_ev_binds = ev_binds_var+ , tcs_unified = unified_var+ , tcs_unif_lvl = unif_lvl_var+ , tcs_count = step_count+ , tcs_inerts = inert_var+ , tcs_worklist = wl_var }++ -- Run the computation+ ; res <- unTcS tcs env++ ; count <- TcM.readTcRef step_count+ ; when (count > 0) $+ csTraceTcM $ return (text "Constraint solver steps =" <+> int count)++ ; when restore_cycles $+ do { inert_set <- TcM.readTcRef inert_var+ ; restoreTyVarCycles inert_set }++#if defined(DEBUG)+ ; ev_binds <- TcM.getTcEvBindsMap ev_binds_var+ ; checkForCyclicBinds ev_binds+#endif++ ; return res }++----------------------------+#if defined(DEBUG)+checkForCyclicBinds :: EvBindMap -> TcM ()+checkForCyclicBinds ev_binds_map+ | null cycles+ = return ()+ | null coercion_cycles+ = TcM.traceTc "Cycle in evidence binds" $ ppr cycles+ | otherwise+ = pprPanic "Cycle in coercion bindings" $ ppr coercion_cycles+ where+ ev_binds = evBindMapBinds ev_binds_map++ cycles :: [[EvBind]]+ cycles = [c | CyclicSCC c <- stronglyConnCompFromEdgedVerticesUniq edges]++ coercion_cycles = [c | c <- cycles, any is_co_bind c]+ is_co_bind (EvBind { eb_lhs = b }) = isEqPrimPred (varType b)++ edges :: [ Node EvVar EvBind ]+ edges = [ DigraphNode bind bndr (nonDetEltsUniqSet (evVarsOfTerm rhs))+ | bind@(EvBind { eb_lhs = bndr, eb_rhs = rhs}) <- bagToList ev_binds ]+ -- It's OK to use nonDetEltsUFM here as+ -- stronglyConnCompFromEdgedVertices is still deterministic even+ -- if the edges are in nondeterministic order as explained in+ -- Note [Deterministic SCC] in GHC.Data.Graph.Directed.+#endif++----------------------------+setEvBindsTcS :: EvBindsVar -> TcS a -> TcS a+setEvBindsTcS ref (TcS thing_inside)+ = TcS $ \ env -> thing_inside (env { tcs_ev_binds = ref })++nestImplicTcS :: EvBindsVar+ -> TcLevel -> TcS a+ -> TcS a+nestImplicTcS ref inner_tclvl (TcS thing_inside)+ = TcS $ \ TcSEnv { tcs_unified = unified_var+ , tcs_inerts = old_inert_var+ , tcs_count = count+ , tcs_unif_lvl = unif_lvl+ } ->+ do { inerts <- TcM.readTcRef old_inert_var+ ; let nest_inert = inerts { inert_cycle_breakers = []+ , inert_cans = (inert_cans inerts)+ { inert_given_eqs = False } }+ -- All other InertSet fields are inherited+ ; new_inert_var <- TcM.newTcRef nest_inert+ ; new_wl_var <- TcM.newTcRef emptyWorkList+ ; let nest_env = TcSEnv { tcs_count = count -- Inherited+ , tcs_unif_lvl = unif_lvl -- Inherited+ , tcs_ev_binds = ref+ , tcs_unified = unified_var+ , tcs_inerts = new_inert_var+ , tcs_worklist = new_wl_var }+ ; res <- TcM.setTcLevel inner_tclvl $+ thing_inside nest_env++ ; out_inert_set <- TcM.readTcRef new_inert_var+ ; restoreTyVarCycles out_inert_set++#if defined(DEBUG)+ -- Perform a check that the thing_inside did not cause cycles+ ; ev_binds <- TcM.getTcEvBindsMap ref+ ; checkForCyclicBinds ev_binds+#endif+ ; return res }++nestTcS :: TcS a -> TcS a+-- Use the current untouchables, augmenting the current+-- evidence bindings, and solved dictionaries+-- But have no effect on the InertCans, or on the inert_famapp_cache+-- (we want to inherit the latter from processing the Givens)+nestTcS (TcS thing_inside)+ = TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var }) ->+ do { inerts <- TcM.readTcRef inerts_var+ ; new_inert_var <- TcM.newTcRef inerts+ ; new_wl_var <- TcM.newTcRef emptyWorkList+ ; let nest_env = env { tcs_inerts = new_inert_var+ , tcs_worklist = new_wl_var }++ ; res <- thing_inside nest_env++ ; new_inerts <- TcM.readTcRef new_inert_var++ -- we want to propagate the safe haskell failures+ ; let old_ic = inert_cans inerts+ new_ic = inert_cans new_inerts+ nxt_ic = old_ic { inert_safehask = inert_safehask new_ic }++ ; TcM.writeTcRef inerts_var -- See Note [Propagate the solved dictionaries]+ (inerts { inert_solved_dicts = inert_solved_dicts new_inerts+ , inert_cans = nxt_ic })++ ; return res }++emitImplicationTcS :: TcLevel -> SkolemInfo+ -> [TcTyVar] -- Skolems+ -> [EvVar] -- Givens+ -> Cts -- Wanteds+ -> TcS TcEvBinds+-- Add an implication to the TcS monad work-list+emitImplicationTcS new_tclvl skol_info skol_tvs givens wanteds+ = do { let wc = emptyWC { wc_simple = wanteds }+ ; imp <- wrapTcS $+ do { ev_binds_var <- TcM.newTcEvBinds+ ; imp <- TcM.newImplication+ ; return (imp { ic_tclvl = new_tclvl+ , ic_skols = skol_tvs+ , ic_given = givens+ , ic_wanted = wc+ , ic_binds = ev_binds_var+ , ic_info = skol_info }) }++ ; emitImplication imp+ ; return (TcEvBinds (ic_binds imp)) }++emitTvImplicationTcS :: TcLevel -> SkolemInfo+ -> [TcTyVar] -- Skolems+ -> Cts -- Wanteds+ -> TcS ()+-- Just like emitImplicationTcS but no givens and no bindings+emitTvImplicationTcS new_tclvl skol_info skol_tvs wanteds+ = do { let wc = emptyWC { wc_simple = wanteds }+ ; imp <- wrapTcS $+ do { ev_binds_var <- TcM.newNoTcEvBinds+ ; imp <- TcM.newImplication+ ; return (imp { ic_tclvl = new_tclvl+ , ic_skols = skol_tvs+ , ic_wanted = wc+ , ic_binds = ev_binds_var+ , ic_info = skol_info }) }++ ; emitImplication imp }+++{- Note [Propagate the solved dictionaries]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+It's really quite important that nestTcS does not discard the solved+dictionaries from the thing_inside.+Consider+ Eq [a]+ forall b. empty => Eq [a]+We solve the simple (Eq [a]), under nestTcS, and then turn our attention to+the implications. It's definitely fine to use the solved dictionaries on+the inner implications, and it can make a significant performance difference+if you do so.+-}++-- Getters and setters of GHC.Tc.Utils.Env fields+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++-- Getter of inerts and worklist+getTcSInertsRef :: TcS (IORef InertSet)+getTcSInertsRef = TcS (return . tcs_inerts)++getTcSWorkListRef :: TcS (IORef WorkList)+getTcSWorkListRef = TcS (return . tcs_worklist)++getTcSInerts :: TcS InertSet+getTcSInerts = getTcSInertsRef >>= readTcRef++setTcSInerts :: InertSet -> TcS ()+setTcSInerts ics = do { r <- getTcSInertsRef; writeTcRef r ics }++getWorkListImplics :: TcS (Bag Implication)+getWorkListImplics+ = do { wl_var <- getTcSWorkListRef+ ; wl_curr <- readTcRef wl_var+ ; return (wl_implics wl_curr) }++pushLevelNoWorkList :: SDoc -> TcS a -> TcS (TcLevel, a)+-- Push the level and run thing_inside+-- However, thing_inside should not generate any work items+#if defined(DEBUG)+pushLevelNoWorkList err_doc (TcS thing_inside)+ = TcS (\env -> TcM.pushTcLevelM $+ thing_inside (env { tcs_worklist = wl_panic })+ )+ where+ wl_panic = pprPanic "GHC.Tc.Solver.Monad.buildImplication" err_doc+ -- This panic checks that the thing-inside+ -- does not emit any work-list constraints+#else+pushLevelNoWorkList _ (TcS thing_inside)+ = TcS (\env -> TcM.pushTcLevelM (thing_inside env)) -- Don't check+#endif++updWorkListTcS :: (WorkList -> WorkList) -> TcS ()+updWorkListTcS f+ = do { wl_var <- getTcSWorkListRef+ ; updTcRef wl_var f }++emitWorkNC :: [CtEvidence] -> TcS ()+emitWorkNC evs+ | null evs+ = return ()+ | otherwise+ = emitWork (map mkNonCanonical evs)++emitWork :: [Ct] -> TcS ()+emitWork [] = return () -- avoid printing, among other work+emitWork cts+ = do { traceTcS "Emitting fresh work" (vcat (map ppr cts))+ ; updWorkListTcS (extendWorkListCts cts) }++emitImplication :: Implication -> TcS ()+emitImplication implic+ = updWorkListTcS (extendWorkListImplic implic)++newTcRef :: a -> TcS (TcRef a)+newTcRef x = wrapTcS (TcM.newTcRef x)++readTcRef :: TcRef a -> TcS a+readTcRef ref = wrapTcS (TcM.readTcRef ref)++writeTcRef :: TcRef a -> a -> TcS ()+writeTcRef ref val = wrapTcS (TcM.writeTcRef ref val)++updTcRef :: TcRef a -> (a->a) -> TcS ()+updTcRef ref upd_fn = wrapTcS (TcM.updTcRef ref upd_fn)++getTcEvBindsVar :: TcS EvBindsVar+getTcEvBindsVar = TcS (return . tcs_ev_binds)++getTcLevel :: TcS TcLevel+getTcLevel = wrapTcS TcM.getTcLevel++getTcEvTyCoVars :: EvBindsVar -> TcS TyCoVarSet+getTcEvTyCoVars ev_binds_var+ = wrapTcS $ TcM.getTcEvTyCoVars ev_binds_var++getTcEvBindsMap :: EvBindsVar -> TcS EvBindMap+getTcEvBindsMap ev_binds_var+ = wrapTcS $ TcM.getTcEvBindsMap ev_binds_var++setTcEvBindsMap :: EvBindsVar -> EvBindMap -> TcS ()+setTcEvBindsMap ev_binds_var binds+ = wrapTcS $ TcM.setTcEvBindsMap ev_binds_var binds++unifyTyVar :: TcTyVar -> TcType -> TcS ()+-- Unify a meta-tyvar with a type+-- We keep track of how many unifications have happened in tcs_unified,+--+-- We should never unify the same variable twice!+unifyTyVar tv ty+ = ASSERT2( isMetaTyVar tv, ppr tv )+ TcS $ \ env ->+ do { TcM.traceTc "unifyTyVar" (ppr tv <+> text ":=" <+> ppr ty)+ ; TcM.writeMetaTyVar tv ty+ ; TcM.updTcRef (tcs_unified env) (+1) }++reportUnifications :: TcS a -> TcS (Int, a)+reportUnifications (TcS thing_inside)+ = TcS $ \ env ->+ do { inner_unified <- TcM.newTcRef 0+ ; res <- thing_inside (env { tcs_unified = inner_unified })+ ; n_unifs <- TcM.readTcRef inner_unified+ ; TcM.updTcRef (tcs_unified env) (+ n_unifs)+ ; return (n_unifs, res) }++getDefaultInfo :: TcS ([Type], (Bool, Bool))+getDefaultInfo = wrapTcS TcM.tcGetDefaultTys++-- Just get some environments needed for instance looking up and matching+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++getInstEnvs :: TcS InstEnvs+getInstEnvs = wrapTcS $ TcM.tcGetInstEnvs++getFamInstEnvs :: TcS (FamInstEnv, FamInstEnv)+getFamInstEnvs = wrapTcS $ FamInst.tcGetFamInstEnvs++getTopEnv :: TcS HscEnv+getTopEnv = wrapTcS $ TcM.getTopEnv++getGblEnv :: TcS TcGblEnv+getGblEnv = wrapTcS $ TcM.getGblEnv++getLclEnv :: TcS TcLclEnv+getLclEnv = wrapTcS $ TcM.getLclEnv++tcLookupClass :: Name -> TcS Class+tcLookupClass c = wrapTcS $ TcM.tcLookupClass c++tcLookupId :: Name -> TcS Id+tcLookupId n = wrapTcS $ TcM.tcLookupId n++-- Setting names as used (used in the deriving of Coercible evidence)+-- Too hackish to expose it to TcS? In that case somehow extract the used+-- constructors from the result of solveInteract+addUsedGREs :: [GlobalRdrElt] -> TcS ()+addUsedGREs gres = wrapTcS $ TcM.addUsedGREs gres++addUsedGRE :: Bool -> GlobalRdrElt -> TcS ()+addUsedGRE warn_if_deprec gre = wrapTcS $ TcM.addUsedGRE warn_if_deprec gre++keepAlive :: Name -> TcS ()+keepAlive = wrapTcS . TcM.keepAlive++-- Various smaller utilities [TODO, maybe will be absorbed in the instance matcher]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++checkWellStagedDFun :: CtLoc -> InstanceWhat -> PredType -> TcS ()+-- Check that we do not try to use an instance before it is available. E.g.+-- instance Eq T where ...+-- f x = $( ... (\(p::T) -> p == p)... )+-- Here we can't use the equality function from the instance in the splice++checkWellStagedDFun loc what pred+ | TopLevInstance { iw_dfun_id = dfun_id } <- what+ , let bind_lvl = TcM.topIdLvl dfun_id+ , bind_lvl > impLevel+ = wrapTcS $ TcM.setCtLocM loc $+ do { use_stage <- TcM.getStage+ ; TcM.checkWellStaged pp_thing bind_lvl (thLevel use_stage) }++ | otherwise+ = return () -- Fast path for common case+ where+ pp_thing = text "instance for" <+> quotes (ppr pred)++pprEq :: TcType -> TcType -> SDoc+pprEq ty1 ty2 = pprParendType ty1 <+> char '~' <+> pprParendType ty2++isFilledMetaTyVar_maybe :: TcTyVar -> TcS (Maybe Type)+isFilledMetaTyVar_maybe tv = wrapTcS (TcM.isFilledMetaTyVar_maybe tv)++isFilledMetaTyVar :: TcTyVar -> TcS Bool+isFilledMetaTyVar tv = wrapTcS (TcM.isFilledMetaTyVar tv)++zonkTyCoVarsAndFV :: TcTyCoVarSet -> TcS TcTyCoVarSet+zonkTyCoVarsAndFV tvs = wrapTcS (TcM.zonkTyCoVarsAndFV tvs)++zonkTyCoVarsAndFVList :: [TcTyCoVar] -> TcS [TcTyCoVar]+zonkTyCoVarsAndFVList tvs = wrapTcS (TcM.zonkTyCoVarsAndFVList tvs)++zonkCo :: Coercion -> TcS Coercion+zonkCo = wrapTcS . TcM.zonkCo++zonkTcType :: TcType -> TcS TcType+zonkTcType ty = wrapTcS (TcM.zonkTcType ty)++zonkTcTypes :: [TcType] -> TcS [TcType]+zonkTcTypes tys = wrapTcS (TcM.zonkTcTypes tys)++zonkTcTyVar :: TcTyVar -> TcS TcType+zonkTcTyVar tv = wrapTcS (TcM.zonkTcTyVar tv)++zonkSimples :: Cts -> TcS Cts+zonkSimples cts = wrapTcS (TcM.zonkSimples cts)++zonkWC :: WantedConstraints -> TcS WantedConstraints+zonkWC wc = wrapTcS (TcM.zonkWC wc)++zonkTyCoVarKind :: TcTyCoVar -> TcS TcTyCoVar+zonkTyCoVarKind tv = wrapTcS (TcM.zonkTyCoVarKind tv)++----------------------------+pprKicked :: Int -> SDoc+pprKicked 0 = empty+pprKicked n = parens (int n <+> text "kicked out")++{- *********************************************************************+* *+* The Unification Level Flag *+* *+********************************************************************* -}++{- Note [The Unification Level Flag]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider a deep tree of implication constraints+ forall[1] a. -- Outer-implic+ C alpha[1] -- Simple+ forall[2] c. ....(C alpha[1]).... -- Implic-1+ forall[2] b. ....(alpha[1] ~ Int).... -- Implic-2++The (C alpha) is insoluble until we know alpha. We solve alpha+by unifying alpha:=Int somewhere deep inside Implic-2. But then we+must try to solve the Outer-implic all over again. This time we can+solve (C alpha) both in Outer-implic, and nested inside Implic-1.++When should we iterate solving a level-n implication?+Answer: if any unification of a tyvar at level n takes place+ in the ic_implics of that implication.++* What if a unification takes place at level n-1? Then don't iterate+ level n, because we'll iterate level n-1, and that will in turn iterate+ level n.++* What if a unification takes place at level n, in the ic_simples of+ level n? No need to track this, because the kick-out mechanism deals+ with it. (We can't drop kick-out in favour of iteration, becuase kick-out+ works for skolem-equalities, not just unifications.)++So the monad-global Unification Level Flag, kept in tcs_unif_lvl keeps+track of+ - Whether any unifications at all have taken place (Nothing => no unifications)+ - If so, what is the outermost level that has seen a unification (Just lvl)++The iteration done in the simplify_loop/maybe_simplify_again loop in GHC.Tc.Solver.++It helpful not to iterate unless there is a chance of progress. #8474 is+an example:++ * There's a deeply-nested chain of implication constraints.+ ?x:alpha => ?y1:beta1 => ... ?yn:betan => [W] ?x:Int++ * From the innermost one we get a [D] alpha[1] ~ Int,+ so we can unify.++ * It's better not to iterate the inner implications, but go all the+ way out to level 1 before iterating -- because iterating level 1+ will iterate the inner levels anyway.++(In the olden days when we "floated" thse Derived constraints, this was+much, much more important -- we got exponential behaviour, as each iteration+produced the same Derived constraint.)+-}+++resetUnificationFlag :: TcS Bool+-- We are at ambient level i+-- If the unification flag = Just i, reset it to Nothing and return True+-- Otherwise leave it unchanged and return False+resetUnificationFlag+ = TcS $ \env ->+ do { let ref = tcs_unif_lvl env+ ; ambient_lvl <- TcM.getTcLevel+ ; mb_lvl <- TcM.readTcRef ref+ ; TcM.traceTc "resetUnificationFlag" $+ vcat [ text "ambient:" <+> ppr ambient_lvl+ , text "unif_lvl:" <+> ppr mb_lvl ]+ ; case mb_lvl of+ Nothing -> return False+ Just unif_lvl | ambient_lvl `strictlyDeeperThan` unif_lvl+ -> return False+ | otherwise+ -> do { TcM.writeTcRef ref Nothing+ ; return True } }++setUnificationFlag :: TcLevel -> TcS ()+-- (setUnificationFlag i) sets the unification level to (Just i)+-- unless it already is (Just j) where j <= i+setUnificationFlag lvl+ = TcS $ \env ->+ do { let ref = tcs_unif_lvl env+ ; mb_lvl <- TcM.readTcRef ref+ ; case mb_lvl of+ Just unif_lvl | lvl `deeperThanOrSame` unif_lvl+ -> return ()+ _ -> TcM.writeTcRef ref (Just lvl) }+++{- *********************************************************************+* *+* Instantiation etc.+* *+********************************************************************* -}++-- Instantiations+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++instDFunType :: DFunId -> [DFunInstType] -> TcS ([TcType], TcThetaType)+instDFunType dfun_id inst_tys+ = wrapTcS $ TcM.instDFunType dfun_id inst_tys++newFlexiTcSTy :: Kind -> TcS TcType+newFlexiTcSTy knd = wrapTcS (TcM.newFlexiTyVarTy knd)++cloneMetaTyVar :: TcTyVar -> TcS TcTyVar+cloneMetaTyVar tv = wrapTcS (TcM.cloneMetaTyVar tv)++instFlexi :: [TKVar] -> TcS TCvSubst+instFlexi = instFlexiX emptyTCvSubst++instFlexiX :: TCvSubst -> [TKVar] -> TcS TCvSubst+instFlexiX subst tvs+ = wrapTcS (foldlM instFlexiHelper subst tvs)++instFlexiHelper :: TCvSubst -> TKVar -> TcM TCvSubst+instFlexiHelper subst tv+ = do { uniq <- TcM.newUnique+ ; details <- TcM.newMetaDetails TauTv+ ; let name = setNameUnique (tyVarName tv) uniq+ kind = substTyUnchecked subst (tyVarKind tv)+ ty' = mkTyVarTy (mkTcTyVar name kind details)+ ; TcM.traceTc "instFlexi" (ppr ty')+ ; return (extendTvSubst subst tv ty') }++matchGlobalInst :: DynFlags+ -> Bool -- True <=> caller is the short-cut solver+ -- See Note [Shortcut solving: overlap]+ -> Class -> [Type] -> TcS TcM.ClsInstResult+matchGlobalInst dflags short_cut cls tys+ = wrapTcS (TcM.matchGlobalInst dflags short_cut cls tys)++tcInstSkolTyVarsX :: TCvSubst -> [TyVar] -> TcS (TCvSubst, [TcTyVar])+tcInstSkolTyVarsX subst tvs = wrapTcS $ TcM.tcInstSkolTyVarsX subst tvs++-- Creating and setting evidence variables and CtFlavors+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++data MaybeNew = Fresh CtEvidence | Cached EvExpr++isFresh :: MaybeNew -> Bool+isFresh (Fresh {}) = True+isFresh (Cached {}) = False++freshGoals :: [MaybeNew] -> [CtEvidence]+freshGoals mns = [ ctev | Fresh ctev <- mns ]++getEvExpr :: MaybeNew -> EvExpr+getEvExpr (Fresh ctev) = ctEvExpr ctev+getEvExpr (Cached evt) = evt++setEvBind :: EvBind -> TcS ()+setEvBind ev_bind+ = do { evb <- getTcEvBindsVar+ ; wrapTcS $ TcM.addTcEvBind evb ev_bind }++-- | Mark variables as used filling a coercion hole+useVars :: CoVarSet -> TcS ()+useVars co_vars+ = do { ev_binds_var <- getTcEvBindsVar+ ; let ref = ebv_tcvs ev_binds_var+ ; wrapTcS $+ do { tcvs <- TcM.readTcRef ref+ ; let tcvs' = tcvs `unionVarSet` co_vars+ ; TcM.writeTcRef ref tcvs' } }++-- | Equalities only+setWantedEq :: TcEvDest -> Coercion -> TcS ()+setWantedEq (HoleDest hole) co+ = do { useVars (coVarsOfCo co)+ ; fillCoercionHole hole co }+setWantedEq (EvVarDest ev) _ = pprPanic "setWantedEq" (ppr ev)++-- | Good for both equalities and non-equalities+setWantedEvTerm :: TcEvDest -> EvTerm -> TcS ()+setWantedEvTerm (HoleDest hole) tm+ | Just co <- evTermCoercion_maybe tm+ = do { useVars (coVarsOfCo co)+ ; fillCoercionHole hole co }+ | otherwise+ = -- See Note [Yukky eq_sel for a HoleDest]+ do { let co_var = coHoleCoVar hole+ ; setEvBind (mkWantedEvBind co_var tm)+ ; fillCoercionHole hole (mkTcCoVarCo co_var) }++setWantedEvTerm (EvVarDest ev_id) tm+ = setEvBind (mkWantedEvBind ev_id tm)++{- Note [Yukky eq_sel for a HoleDest]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+How can it be that a Wanted with HoleDest gets evidence that isn't+just a coercion? i.e. evTermCoercion_maybe returns Nothing.++Consider [G] forall a. blah => a ~ T+ [W] S ~# T++Then doTopReactEqPred carefully looks up the (boxed) constraint (S ~+T) in the quantified constraints, and wraps the (boxed) evidence it+gets back in an eq_sel to extract the unboxed (S ~# T). We can't put+that term into a coercion, so we add a value binding+ h = eq_sel (...)+and the coercion variable h to fill the coercion hole.+We even re-use the CoHole's Id for this binding!++Yuk!+-}++fillCoercionHole :: CoercionHole -> Coercion -> TcS ()+fillCoercionHole hole co+ = do { wrapTcS $ TcM.fillCoercionHole hole co+ ; kickOutAfterFillingCoercionHole hole co }++setEvBindIfWanted :: CtEvidence -> EvTerm -> TcS ()+setEvBindIfWanted ev tm+ = case ev of+ CtWanted { ctev_dest = dest } -> setWantedEvTerm dest tm+ _ -> return ()++newTcEvBinds :: TcS EvBindsVar+newTcEvBinds = wrapTcS TcM.newTcEvBinds++newNoTcEvBinds :: TcS EvBindsVar+newNoTcEvBinds = wrapTcS TcM.newNoTcEvBinds++newEvVar :: TcPredType -> TcS EvVar+newEvVar pred = wrapTcS (TcM.newEvVar pred)++newGivenEvVar :: CtLoc -> (TcPredType, EvTerm) -> TcS CtEvidence+-- Make a new variable of the given PredType,+-- immediately bind it to the given term+-- and return its CtEvidence+-- See Note [Bind new Givens immediately] in GHC.Tc.Types.Constraint+newGivenEvVar loc (pred, rhs)+ = do { new_ev <- newBoundEvVarId pred rhs+ ; return (CtGiven { ctev_pred = pred, ctev_evar = new_ev, ctev_loc = loc }) }++-- | Make a new 'Id' of the given type, bound (in the monad's EvBinds) to the+-- given term+newBoundEvVarId :: TcPredType -> EvTerm -> TcS EvVar+newBoundEvVarId pred rhs+ = do { new_ev <- newEvVar pred+ ; setEvBind (mkGivenEvBind new_ev rhs)+ ; return new_ev }++newGivenEvVars :: CtLoc -> [(TcPredType, EvTerm)] -> TcS [CtEvidence]+newGivenEvVars loc pts = mapM (newGivenEvVar loc) pts++emitNewWantedEq :: CtLoc -> Role -> TcType -> TcType -> TcS Coercion+-- | Emit a new Wanted equality into the work-list+emitNewWantedEq loc role ty1 ty2+ = do { (ev, co) <- newWantedEq loc role ty1 ty2+ ; updWorkListTcS (extendWorkListEq (mkNonCanonical ev))+ ; return co }++-- | Make a new equality CtEvidence+newWantedEq :: CtLoc -> Role -> TcType -> TcType+ -> TcS (CtEvidence, Coercion)+newWantedEq = newWantedEq_SI WDeriv++newWantedEq_SI :: ShadowInfo -> CtLoc -> Role+ -> TcType -> TcType+ -> TcS (CtEvidence, Coercion)+newWantedEq_SI si loc role ty1 ty2+ = do { hole <- wrapTcS $ TcM.newCoercionHole pty+ ; traceTcS "Emitting new coercion hole" (ppr hole <+> dcolon <+> ppr pty)+ ; return ( CtWanted { ctev_pred = pty, ctev_dest = HoleDest hole+ , ctev_nosh = si+ , ctev_loc = loc}+ , mkHoleCo hole ) }+ where+ pty = mkPrimEqPredRole role ty1 ty2++-- no equalities here. Use newWantedEq instead+newWantedEvVarNC :: CtLoc -> TcPredType -> TcS CtEvidence+newWantedEvVarNC = newWantedEvVarNC_SI WDeriv++newWantedEvVarNC_SI :: ShadowInfo -> CtLoc -> TcPredType -> TcS CtEvidence+-- Don't look up in the solved/inerts; we know it's not there+newWantedEvVarNC_SI si loc pty+ = do { new_ev <- newEvVar pty+ ; traceTcS "Emitting new wanted" (ppr new_ev <+> dcolon <+> ppr pty $$+ pprCtLoc loc)+ ; return (CtWanted { ctev_pred = pty, ctev_dest = EvVarDest new_ev+ , ctev_nosh = si+ , ctev_loc = loc })}++newWantedEvVar :: CtLoc -> TcPredType -> TcS MaybeNew+newWantedEvVar = newWantedEvVar_SI WDeriv++newWantedEvVar_SI :: ShadowInfo -> CtLoc -> TcPredType -> TcS MaybeNew+-- For anything except ClassPred, this is the same as newWantedEvVarNC+newWantedEvVar_SI si loc pty+ = do { mb_ct <- lookupInInerts loc pty+ ; case mb_ct of+ Just ctev+ | not (isDerived ctev)+ -> do { traceTcS "newWantedEvVar/cache hit" $ ppr ctev+ ; return $ Cached (ctEvExpr ctev) }+ _ -> do { ctev <- newWantedEvVarNC_SI si loc pty+ ; return (Fresh ctev) } }++newWanted :: CtLoc -> PredType -> TcS MaybeNew+-- Deals with both equalities and non equalities. Tries to look+-- up non-equalities in the cache+newWanted = newWanted_SI WDeriv++newWanted_SI :: ShadowInfo -> CtLoc -> PredType -> TcS MaybeNew+newWanted_SI si loc pty+ | Just (role, ty1, ty2) <- getEqPredTys_maybe pty+ = Fresh . fst <$> newWantedEq_SI si loc role ty1 ty2+ | otherwise+ = newWantedEvVar_SI si loc pty++-- deals with both equalities and non equalities. Doesn't do any cache lookups.+newWantedNC :: CtLoc -> PredType -> TcS CtEvidence+newWantedNC loc pty+ | Just (role, ty1, ty2) <- getEqPredTys_maybe pty+ = fst <$> newWantedEq loc role ty1 ty2+ | otherwise+ = newWantedEvVarNC loc pty++emitNewDeriveds :: CtLoc -> [TcPredType] -> TcS ()+emitNewDeriveds loc preds+ | null preds+ = return ()+ | otherwise+ = do { evs <- mapM (newDerivedNC loc) preds+ ; traceTcS "Emitting new deriveds" (ppr evs)+ ; updWorkListTcS (extendWorkListDeriveds evs) }++emitNewDerivedEq :: CtLoc -> Role -> TcType -> TcType -> TcS ()+-- Create new equality Derived and put it in the work list+-- There's no caching, no lookupInInerts+emitNewDerivedEq loc role ty1 ty2+ = do { ev <- newDerivedNC loc (mkPrimEqPredRole role ty1 ty2)+ ; traceTcS "Emitting new derived equality" (ppr ev $$ pprCtLoc loc)+ ; updWorkListTcS (extendWorkListEq (mkNonCanonical ev)) }+ -- Very important: put in the wl_eqs+ -- See Note [Prioritise equalities] (Avoiding fundep iteration)++newDerivedNC :: CtLoc -> TcPredType -> TcS CtEvidence+newDerivedNC loc pred+ = return $ CtDerived { ctev_pred = pred, ctev_loc = loc }++-- --------- Check done in GHC.Tc.Solver.Interact.selectNewWorkItem???? ---------+-- | Checks if the depth of the given location is too much. Fails if+-- it's too big, with an appropriate error message.+checkReductionDepth :: CtLoc -> TcType -- ^ type being reduced+ -> TcS ()+checkReductionDepth loc ty+ = do { dflags <- getDynFlags+ ; when (subGoalDepthExceeded dflags (ctLocDepth loc)) $+ wrapErrTcS $+ solverDepthErrorTcS loc ty }++matchFam :: TyCon -> [Type] -> TcS (Maybe (CoercionN, TcType))+-- Given (F tys) return (ty, co), where co :: ty ~N F tys+matchFam tycon args = fmap (fmap (first mkTcSymCo)) $ wrapTcS $ matchFamTcM tycon args++matchFamTcM :: TyCon -> [Type] -> TcM (Maybe (CoercionN, TcType))+-- Given (F tys) return (ty, co), where co :: F tys ~N ty+matchFamTcM tycon args+ = do { fam_envs <- FamInst.tcGetFamInstEnvs+ ; let match_fam_result+ = reduceTyFamApp_maybe fam_envs Nominal tycon args+ ; TcM.traceTc "matchFamTcM" $+ vcat [ text "Matching:" <+> ppr (mkTyConApp tycon args)+ , ppr_res match_fam_result ]+ ; return match_fam_result }+ where+ ppr_res Nothing = text "Match failed"+ ppr_res (Just (co,ty)) = hang (text "Match succeeded:")+ 2 (vcat [ text "Rewrites to:" <+> ppr ty+ , text "Coercion:" <+> ppr co ])++{-+Note [Residual implications]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The wl_implics in the WorkList are the residual implication+constraints that are generated while solving or canonicalising the+current worklist. Specifically, when canonicalising+ (forall a. t1 ~ forall a. t2)+from which we get the implication+ (forall a. t1 ~ t2)+See GHC.Tc.Solver.Monad.deferTcSForAllEq+-}++{-+************************************************************************+* *+ Breaking type variable cycles+* *+************************************************************************+-}++-- | Replace all type family applications in the RHS with fresh variables,+-- emitting givens that relate the type family application to the variable.+-- See Note [Type variable cycles in Givens] in GHC.Tc.Solver.Canonical.+breakTyVarCycle :: CtLoc+ -> TcType -- the RHS+ -> TcS TcType -- new RHS that doesn't have any type families+-- This could be considerably more efficient. See Detail (5) of Note.+breakTyVarCycle loc = go+ where+ go ty | Just ty' <- rewriterView ty = go ty'+ go (Rep.TyConApp tc tys)+ | isTypeFamilyTyCon tc+ = do { let (fun_args, extra_args) = splitAt (tyConArity tc) tys+ fun_app = mkTyConApp tc fun_args+ fun_app_kind = tcTypeKind fun_app+ ; new_tv <- wrapTcS (TcM.newCycleBreakerTyVar fun_app_kind)+ ; let new_ty = mkTyVarTy new_tv+ given_pred = mkHeteroPrimEqPred fun_app_kind fun_app_kind+ fun_app new_ty+ given_term = evCoercion $ mkNomReflCo new_ty -- See Detail (4) of Note+ ; new_given <- newGivenEvVar loc (given_pred, given_term)+ ; traceTcS "breakTyVarCycle replacing type family" (ppr new_given)+ ; emitWorkNC [new_given]+ ; updInertTcS $ \is ->+ is { inert_cycle_breakers = (new_tv, fun_app) :+ inert_cycle_breakers is }+ ; extra_args' <- mapM go extra_args+ ; return (mkAppTys new_ty extra_args') }+ -- Worried that this substitution will change kinds?+ -- See Detail (3) of Note++ | otherwise+ = mkTyConApp tc <$> mapM go tys++ go (Rep.AppTy ty1 ty2) = mkAppTy <$> go ty1 <*> go ty2+ go (Rep.FunTy vis w arg res) = mkFunTy vis <$> go w <*> go arg <*> go res+ go (Rep.CastTy ty co) = mkCastTy <$> go ty <*> pure co++ go ty@(Rep.TyVarTy {}) = return ty+ go ty@(Rep.LitTy {}) = return ty+ go ty@(Rep.ForAllTy {}) = return ty -- See Detail (1) of Note+ go ty@(Rep.CoercionTy {}) = return ty -- See Detail (2) of Note++-- | Fill in CycleBreakerTvs with the variables they stand for.+-- See Note [Type variable cycles in Givens] 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++-- Unwrap a type synonym only when either:+-- The type synonym is forgetful, or+-- the type synonym mentions a type family in its expansion+-- See Note [Rewriting synonyms] in GHC.Tc.Solver.Rewrite.+rewriterView :: TcType -> Maybe TcType+rewriterView ty@(Rep.TyConApp tc _)+ | isForgetfulSynTyCon tc || (isTypeSynonymTyCon tc && not (isFamFreeTyCon tc))+ = tcView ty+rewriterView _other = Nothing
+ compiler/GHC/Tc/Solver/Rewrite.hs view
@@ -0,0 +1,1033 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveFunctor #-}++{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}++module GHC.Tc.Solver.Rewrite(+ rewrite, rewriteKind, rewriteArgsNom,+ rewriteType+ ) where++#include "GhclibHsVersions.h"++import GHC.Prelude++import GHC.Core.TyCo.Ppr ( pprTyVar )+import GHC.Tc.Types.Constraint+import GHC.Core.Predicate+import GHC.Tc.Utils.TcType+import GHC.Core.Type+import GHC.Tc.Types.Evidence+import GHC.Core.TyCon+import GHC.Core.TyCo.Rep -- performs delicate algorithm on types+import GHC.Core.Coercion+import GHC.Types.Var+import GHC.Types.Var.Set+import GHC.Types.Var.Env+import GHC.Driver.Session+import GHC.Utils.Outputable+import GHC.Utils.Panic+import GHC.Tc.Solver.Monad as TcS++import GHC.Utils.Misc+import GHC.Data.Maybe+import Control.Monad+import GHC.Utils.Monad ( zipWith3M )+import Data.List.NonEmpty ( NonEmpty(..) )++import Control.Arrow ( first )++{-+************************************************************************+* *+* RewriteEnv & RewriteM+* The rewriting environment & monad+* *+************************************************************************+-}++data RewriteEnv+ = FE { fe_loc :: !CtLoc -- See Note [Rewriter CtLoc]+ , fe_flavour :: !CtFlavour+ , fe_eq_rel :: !EqRel -- See Note [Rewriter EqRels]+ }++-- | The 'RewriteM' monad is a wrapper around 'TcS' with a 'RewriteEnv'+newtype RewriteM a+ = RewriteM { runRewriteM :: RewriteEnv -> TcS a }+ deriving (Functor)++instance Monad RewriteM where+ m >>= k = RewriteM $ \env ->+ do { a <- runRewriteM m env+ ; runRewriteM (k a) env }++instance Applicative RewriteM where+ pure x = RewriteM $ const (pure x)+ (<*>) = ap++instance HasDynFlags RewriteM where+ getDynFlags = liftTcS getDynFlags++liftTcS :: TcS a -> RewriteM a+liftTcS thing_inside+ = RewriteM $ const thing_inside++-- convenient wrapper when you have a CtEvidence describing+-- the rewriting operation+runRewriteCtEv :: CtEvidence -> RewriteM a -> TcS a+runRewriteCtEv ev+ = runRewrite (ctEvLoc ev) (ctEvFlavour ev) (ctEvEqRel ev)++-- Run thing_inside (which does the rewriting)+runRewrite :: CtLoc -> CtFlavour -> EqRel -> RewriteM a -> TcS a+runRewrite loc flav eq_rel thing_inside+ = runRewriteM thing_inside fmode+ where+ fmode = FE { fe_loc = loc+ , fe_flavour = flav+ , fe_eq_rel = eq_rel }++traceRewriteM :: String -> SDoc -> RewriteM ()+traceRewriteM herald doc = liftTcS $ traceTcS herald doc+{-# INLINE traceRewriteM #-} -- see Note [INLINE conditional tracing utilities]++getRewriteEnvField :: (RewriteEnv -> a) -> RewriteM a+getRewriteEnvField accessor+ = RewriteM $ \env -> return (accessor env)++getEqRel :: RewriteM EqRel+getEqRel = getRewriteEnvField fe_eq_rel++getRole :: RewriteM Role+getRole = eqRelRole <$> getEqRel++getFlavour :: RewriteM CtFlavour+getFlavour = getRewriteEnvField fe_flavour++getFlavourRole :: RewriteM CtFlavourRole+getFlavourRole+ = do { flavour <- getFlavour+ ; eq_rel <- getEqRel+ ; return (flavour, eq_rel) }++getLoc :: RewriteM CtLoc+getLoc = getRewriteEnvField fe_loc++checkStackDepth :: Type -> RewriteM ()+checkStackDepth ty+ = do { loc <- getLoc+ ; liftTcS $ checkReductionDepth loc ty }++-- | Change the 'EqRel' in a 'RewriteM'.+setEqRel :: EqRel -> RewriteM a -> RewriteM a+setEqRel new_eq_rel thing_inside+ = RewriteM $ \env ->+ if new_eq_rel == fe_eq_rel env+ then runRewriteM thing_inside env+ else runRewriteM thing_inside (env { fe_eq_rel = new_eq_rel })+{-# INLINE setEqRel #-}++-- | Make sure that rewriting actually produces a coercion (in other+-- words, make sure our flavour is not Derived)+-- Note [No derived kind equalities]+noBogusCoercions :: RewriteM a -> RewriteM a+noBogusCoercions thing_inside+ = RewriteM $ \env ->+ -- No new thunk is made if the flavour hasn't changed (note the bang).+ let !env' = case fe_flavour env of+ Derived -> env { fe_flavour = Wanted WDeriv }+ _ -> env+ in+ runRewriteM thing_inside env'++bumpDepth :: RewriteM a -> RewriteM a+bumpDepth (RewriteM thing_inside)+ = RewriteM $ \env -> do+ -- bumpDepth can be called a lot during rewriting so we force the+ -- new env to avoid accumulating thunks.+ { let !env' = env { fe_loc = bumpCtLocDepth (fe_loc env) }+ ; thing_inside env' }++{-+Note [Rewriter EqRels]+~~~~~~~~~~~~~~~~~~~~~~~+When rewriting, we need to know which equality relation -- nominal+or representation -- we should be respecting. The only difference is+that we rewrite variables by representational equalities when fe_eq_rel+is ReprEq, and that we unwrap newtypes when rewriting w.r.t.+representational equality.++Note [Rewriter CtLoc]+~~~~~~~~~~~~~~~~~~~~~~+The rewriter does eager type-family reduction.+Type families might loop, and we+don't want GHC to do so. A natural solution is to have a bounded depth+to these processes. A central difficulty is that such a solution isn't+quite compositional. For example, say it takes F Int 10 steps to get to Bool.+How many steps does it take to get from F Int -> F Int to Bool -> Bool?+10? 20? What about getting from Const Char (F Int) to Char? 11? 1? Hard to+know and hard to track. So, we punt, essentially. We store a CtLoc in+the RewriteEnv and just update the environment when recurring. In the+TyConApp case, where there may be multiple type families to rewrite,+we just copy the current CtLoc into each branch. If any branch hits the+stack limit, then the whole thing fails.++A consequence of this is that setting the stack limits appropriately+will be essentially impossible. So, the official recommendation if a+stack limit is hit is to disable the check entirely. Otherwise, there+will be baffling, unpredictable errors.++Note [Phantoms in the rewriter]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we have++data Proxy p = Proxy++and we're rewriting (Proxy ty) w.r.t. ReprEq. Then, we know that `ty`+is really irrelevant -- it will be ignored when solving for representational+equality later on. So, we omit rewriting `ty` entirely. This may+violate the expectation of "xi"s for a bit, but the canonicaliser will+soon throw out the phantoms when decomposing a TyConApp. (Or, the+canonicaliser will emit an insoluble, in which case we get+a better error message anyway.)++Note [No derived kind equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+A kind-level coercion can appear in types, via mkCastTy. So, whenever+we are generating a coercion in a dependent context (in other words,+in a kind) we need to make sure that our flavour is never Derived+(as Derived constraints have no evidence). The noBogusCoercions function+changes the flavour from Derived just for this purpose.++-}++{- *********************************************************************+* *+* Externally callable rewriting functions *+* *+************************************************************************+-}++-- | See Note [Rewriting].+-- If (xi, co) <- rewrite mode ev ty, then co :: xi ~r ty+-- where r is the role in @ev@.+rewrite :: CtEvidence -> TcType+ -> TcS (Xi, TcCoercion)+rewrite ev ty+ = do { traceTcS "rewrite {" (ppr ty)+ ; (ty', co) <- runRewriteCtEv ev (rewrite_one ty)+ ; traceTcS "rewrite }" (ppr ty')+ ; return (ty', co) }++-- specialized to rewriting kinds: never Derived, always Nominal+-- See Note [No derived kind equalities]+-- See Note [Rewriting]+rewriteKind :: CtLoc -> CtFlavour -> TcType -> TcS (Xi, TcCoercionN)+rewriteKind loc flav ty+ = do { traceTcS "rewriteKind {" (ppr flav <+> ppr ty)+ ; let flav' = case flav of+ Derived -> Wanted WDeriv -- the WDeriv/WOnly choice matters not+ _ -> flav+ ; (ty', co) <- runRewrite loc flav' NomEq (rewrite_one ty)+ ; traceTcS "rewriteKind }" (ppr ty' $$ ppr co) -- co is never a panic+ ; return (ty', co) }++-- See Note [Rewriting]+rewriteArgsNom :: CtEvidence -> TyCon -> [TcType] -> TcS ([Xi], [TcCoercion])+-- Externally-callable, hence runRewrite+-- Rewrite a vector of types all at once; in fact they are+-- always the arguments of type family or class, so+-- ctEvFlavour ev = Nominal+-- and we want to rewrite all at nominal role+-- The kind passed in is the kind of the type family or class, call it T+-- The kind of T args must be constant (i.e. not depend on the args)+--+-- For Derived constraints the returned coercion may be undefined+-- because rewriting may use a Derived equality ([D] a ~ ty)+rewriteArgsNom ev tc tys+ = do { traceTcS "rewrite_args {" (vcat (map ppr tys))+ ; (tys', cos, kind_co)+ <- runRewriteCtEv ev (rewrite_args_tc tc Nothing tys)+ ; MASSERT( isReflMCo kind_co )+ ; traceTcS "rewrite }" (vcat (map ppr tys'))+ ; return (tys', cos) }++-- | Rewrite a type w.r.t. nominal equality. This is useful to rewrite+-- a type w.r.t. any givens. It does not do type-family reduction. This+-- will never emit new constraints. Call this when the inert set contains+-- only givens.+rewriteType :: CtLoc -> TcType -> TcS TcType+rewriteType loc ty+ = do { (xi, _) <- runRewrite loc Given NomEq $+ rewrite_one ty+ -- use Given flavor so that it is rewritten+ -- only w.r.t. Givens, never Wanteds/Deriveds+ -- (Shouldn't matter, if only Givens are present+ -- anyway)+ ; return xi }++{- *********************************************************************+* *+* The main rewriting functions+* *+********************************************************************* -}++{- Note [Rewriting]+~~~~~~~~~~~~~~~~~~~~+ rewrite ty ==> (xi, co)+ where+ xi has no reducible type functions+ has no skolems that are mapped in the inert set+ has no filled-in metavariables+ co :: xi ~ ty++Key invariants:+ (F0) co :: xi ~ zonk(ty') where zonk(ty') ~ zonk(ty)+ (F1) tcTypeKind(xi) succeeds and returns a fully zonked kind+ (F2) tcTypeKind(xi) `eqType` zonk(tcTypeKind(ty))++Note that it is rewrite's job to try to reduce *every type function it sees*.++Rewriting also:+ * zonks, removing any metavariables, and+ * applies the substitution embodied in the inert set++Because rewriting zonks and the returned coercion ("co" above) is also+zonked, it's possible that (co :: xi ~ ty) isn't quite true. So, instead,+we can rely on this fact:++ (F0) co :: xi ~ zonk(ty'), where zonk(ty') ~ zonk(ty)++Note that the left-hand type of co is *always* precisely xi. The right-hand+type may or may not be ty, however: if ty has unzonked filled-in metavariables,+then the right-hand type of co will be the zonk-equal to ty.+It is for this reason that we+occasionally have to explicitly zonk, when (co :: xi ~ ty) is important+even before we zonk the whole program. For example, see the RTRNotFollowed+case in rewriteTyVar.++Why have these invariants on rewriting? Because we sometimes use tcTypeKind+during canonicalisation, and we want this kind to be zonked (e.g., see+GHC.Tc.Solver.Canonical.canEqCanLHS).++Rewriting is always homogeneous. That is, the kind of the result of rewriting is+always the same as the kind of the input, modulo zonking. More formally:++ (F2) tcTypeKind(xi) `eqType` zonk(tcTypeKind(ty))++This invariant means that the kind of a rewritten type might not itself be rewritten.++Note that we prefer to leave type synonyms unexpanded when possible,+so when the rewriter encounters one, it first asks whether its+transitive expansion contains any type function applications or is+forgetful -- that is, omits one or more type variables in its RHS. If so,+it expands the synonym and proceeds; if not, it simply returns the+unexpanded synonym. See also Note [Rewriting synonyms].++Note [rewrite_args performance]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In programs with lots of type-level evaluation, rewrite_args becomes+part of a tight loop. For example, see test perf/compiler/T9872a, which+calls rewrite_args a whopping 7,106,808 times. It is thus important+that rewrite_args be efficient.++Performance testing showed that the current implementation is indeed+efficient. It's critically important that zipWithAndUnzipM be+specialized to TcS, and it's also quite helpful to actually `inline`+it. On test T9872a, here are the allocation stats (Dec 16, 2014):++ * Unspecialized, uninlined: 8,472,613,440 bytes allocated in the heap+ * Specialized, uninlined: 6,639,253,488 bytes allocated in the heap+ * Specialized, inlined: 6,281,539,792 bytes allocated in the heap++To improve performance even further, rewrite_args_nom is split off+from rewrite_args, as nominal equality is the common case. This would+be natural to write using mapAndUnzipM, but even inlined, that function+is not as performant as a hand-written loop.++ * mapAndUnzipM, inlined: 7,463,047,432 bytes allocated in the heap+ * hand-written recursion: 5,848,602,848 bytes allocated in the heap++If you make any change here, pay close attention to the T9872{a,b,c} tests+and T5321Fun.++If we need to make this yet more performant, a possible way forward is to+duplicate the rewriter code for the nominal case, and make that case+faster. This doesn't seem quite worth it, yet.++Note [rewrite_exact_fam_app performance]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Once we've got a rewritten rhs, we extend the famapp-cache to record+the result. Doing so can save lots of work when the same redex shows up more+than once. Note that we record the link from the redex all the way to its+*final* value, not just the single step reduction.++If we can reduce the family application right away (the first call+to try_to_reduce), we do *not* add to the cache. There are two possibilities+here: 1) we just read the result from the cache, or 2) we used one type+family instance. In either case, recording the result in the cache doesn't+save much effort the next time around. And adding to the cache here is+actually disastrous: it more than doubles the allocations for T9872a. So+we skip adding to the cache here.+-}++{-# INLINE rewrite_args_tc #-}+rewrite_args_tc+ :: TyCon -- T+ -> Maybe [Role] -- Nothing: ambient role is Nominal; all args are Nominal+ -- Otherwise: no assumptions; use roles provided+ -> [Type] -- Arg types [t1,..,tn]+ -> RewriteM ( [Xi] -- List of rewritten args [x1,..,xn]+ -- 1-1 corresp with [t1,..,tn]+ , [Coercion] -- List of arg coercions [co1,..,con]+ -- 1-1 corresp with [t1,..,tn]+ -- coi :: xi ~r ti+ , MCoercionN) -- Result coercion, rco+ -- rco : (T t1..tn) ~N (T (x1 |> co1) .. (xn |> con))+rewrite_args_tc tc = rewrite_args all_bndrs any_named_bndrs inner_ki emptyVarSet+ -- NB: TyCon kinds are always closed+ where+ (bndrs, named)+ = ty_con_binders_ty_binders' (tyConBinders tc)+ -- it's possible that the result kind has arrows (for, e.g., a type family)+ -- so we must split it+ (inner_bndrs, inner_ki, inner_named) = split_pi_tys' (tyConResKind tc)+ !all_bndrs = bndrs `chkAppend` inner_bndrs+ !any_named_bndrs = named || inner_named+ -- NB: Those bangs there drop allocations in T9872{a,c,d} by 8%.++{-# INLINE rewrite_args #-}+rewrite_args :: [TyCoBinder] -> Bool -- Binders, and True iff any of them are+ -- named.+ -> Kind -> TcTyCoVarSet -- function kind; kind's free vars+ -> Maybe [Role] -> [Type] -- these are in 1-to-1 correspondence+ -- Nothing: use all Nominal+ -> RewriteM ([Xi], [Coercion], MCoercionN)+-- Coercions :: Xi ~ Type, at roles given+-- Third coercion :: tcTypeKind(fun xis) ~N tcTypeKind(fun tys)+-- That is, the third coercion relates the kind of some function (whose kind is+-- passed as the first parameter) instantiated at xis to the kind of that+-- function instantiated at the tys. This is useful in keeping rewriting+-- homoegeneous. The list of roles must be at least as long as the list of+-- types.+rewrite_args orig_binders+ any_named_bndrs+ orig_inner_ki+ orig_fvs+ orig_m_roles+ orig_tys+ = case (orig_m_roles, any_named_bndrs) of+ (Nothing, False) -> rewrite_args_fast orig_tys+ _ -> rewrite_args_slow orig_binders orig_inner_ki orig_fvs orig_roles orig_tys+ where orig_roles = fromMaybe (repeat Nominal) orig_m_roles++{-# INLINE rewrite_args_fast #-}+-- | fast path rewrite_args, in which none of the binders are named and+-- therefore we can avoid tracking a lifting context.+-- There are many bang patterns in here. It's been observed that they+-- greatly improve performance of an optimized build.+-- The T9872 test cases are good witnesses of this fact.+rewrite_args_fast :: [Type]+ -> RewriteM ([Xi], [Coercion], MCoercionN)+rewrite_args_fast orig_tys+ = fmap finish (iterate orig_tys)+ where++ iterate :: [Type]+ -> RewriteM ([Xi], [Coercion])+ iterate (ty:tys) = do+ (xi, co) <- rewrite_one ty+ (xis, cos) <- iterate tys+ pure (xi : xis, co : cos)+ iterate [] = pure ([], [])++ {-# INLINE finish #-}+ finish :: ([Xi], [Coercion]) -> ([Xi], [Coercion], MCoercionN)+ finish (xis, cos) = (xis, cos, MRefl)++{-# INLINE rewrite_args_slow #-}+-- | Slow path, compared to rewrite_args_fast, because this one must track+-- a lifting context.+rewrite_args_slow :: [TyCoBinder] -> Kind -> TcTyCoVarSet+ -> [Role] -> [Type]+ -> RewriteM ([Xi], [Coercion], MCoercionN)+rewrite_args_slow binders inner_ki fvs roles tys+-- Arguments used dependently must be rewritten with proper coercions, but+-- we're not guaranteed to get a proper coercion when rewriting with the+-- "Derived" flavour. So we must call noBogusCoercions when rewriting arguments+-- corresponding to binders that are dependent. However, we might legitimately+-- have *more* arguments than binders, in the case that the inner_ki is a variable+-- that gets instantiated with a Π-type. We conservatively choose not to produce+-- bogus coercions for these, too. Note that this might miss an opportunity for+-- a Derived rewriting a Derived. The solution would be to generate evidence for+-- Deriveds, thus avoiding this whole noBogusCoercions idea. See also+-- Note [No derived kind equalities]+ = do { rewritten_args <- zipWith3M fl (map isNamedBinder binders ++ repeat True)+ roles tys+ ; return (simplifyArgsWorker binders inner_ki fvs roles rewritten_args) }+ where+ {-# INLINE fl #-}+ fl :: Bool -- must we ensure to produce a real coercion here?+ -- see comment at top of function+ -> Role -> Type -> RewriteM (Xi, Coercion)+ fl True r ty = noBogusCoercions $ fl1 r ty+ fl False r ty = fl1 r ty++ {-# INLINE fl1 #-}+ fl1 :: Role -> Type -> RewriteM (Xi, Coercion)+ fl1 Nominal ty+ = setEqRel NomEq $+ rewrite_one ty++ fl1 Representational ty+ = setEqRel ReprEq $+ rewrite_one ty++ fl1 Phantom ty+ -- See Note [Phantoms in the rewriter]+ = do { ty <- liftTcS $ zonkTcType ty+ ; return (ty, mkReflCo Phantom ty) }++------------------+rewrite_one :: TcType -> RewriteM (Xi, Coercion)+-- Rewrite a type to get rid of type function applications, returning+-- the new type-function-free type, and a collection of new equality+-- constraints. See Note [Rewriting] for more detail.+--+-- Postcondition: Coercion :: Xi ~ TcType+-- The role on the result coercion matches the EqRel in the RewriteEnv++rewrite_one ty+ | Just ty' <- rewriterView ty -- See Note [Rewriting synonyms]+ = rewrite_one ty'++rewrite_one xi@(LitTy {})+ = do { role <- getRole+ ; return (xi, mkReflCo role xi) }++rewrite_one (TyVarTy tv)+ = rewriteTyVar tv++rewrite_one (AppTy ty1 ty2)+ = rewrite_app_tys ty1 [ty2]++rewrite_one (TyConApp tc tys)+ -- If it's a type family application, try to reduce it+ | isTypeFamilyTyCon tc+ = rewrite_fam_app tc tys++ -- For * a normal data type application+ -- * data family application+ -- we just recursively rewrite the arguments.+ | otherwise+ = rewrite_ty_con_app tc tys++rewrite_one ty@(FunTy { ft_mult = mult, ft_arg = ty1, ft_res = ty2 })+ = do { (xi1,co1) <- rewrite_one ty1+ ; (xi2,co2) <- rewrite_one ty2+ ; (xi3,co3) <- setEqRel NomEq $ rewrite_one mult+ ; role <- getRole+ ; return (ty { ft_mult = xi3, ft_arg = xi1, ft_res = xi2 }+ , mkFunCo role co3 co1 co2) }++rewrite_one ty@(ForAllTy {})+-- TODO (RAE): This is inadequate, as it doesn't rewrite the kind of+-- the bound tyvar. Doing so will require carrying around a substitution+-- and the usual substTyVarBndr-like silliness. Argh.++-- We allow for-alls when, but only when, no type function+-- applications inside the forall involve the bound type variables.+ = do { let (bndrs, rho) = tcSplitForAllTyVarBinders ty+ tvs = binderVars bndrs+ ; (rho', co) <- rewrite_one rho+ ; return (mkForAllTys bndrs rho', mkHomoForAllCos tvs co) }++rewrite_one (CastTy ty g)+ = do { (xi, co) <- rewrite_one ty+ ; (g', _) <- rewrite_co g+ ; role <- getRole+ ; return (mkCastTy xi g', castCoercionKind1 co role xi ty g') }+ -- It makes a /big/ difference to call castCoercionKind1 not+ -- the more general castCoercionKind2.+ -- See Note [castCoercionKind1] in GHC.Core.Coercion++rewrite_one (CoercionTy co) = first mkCoercionTy <$> rewrite_co co++-- | "Rewrite" a coercion. Really, just zonk it so we can uphold+-- (F1) of Note [Rewriting]+rewrite_co :: Coercion -> RewriteM (Coercion, Coercion)+rewrite_co co+ = do { co <- liftTcS $ zonkCo co+ ; env_role <- getRole+ ; let co' = mkTcReflCo env_role (mkCoercionTy co)+ ; return (co, co') }++-- rewrite (nested) AppTys+rewrite_app_tys :: Type -> [Type] -> RewriteM (Xi, Coercion)+-- commoning up nested applications allows us to look up the function's kind+-- only once. Without commoning up like this, we would spend a quadratic amount+-- of time looking up functions' types+rewrite_app_tys (AppTy ty1 ty2) tys = rewrite_app_tys ty1 (ty2:tys)+rewrite_app_tys fun_ty arg_tys+ = do { (fun_xi, fun_co) <- rewrite_one fun_ty+ ; rewrite_app_ty_args fun_xi fun_co arg_tys }++-- Given a rewritten function (with the coercion produced by rewriting) and+-- a bunch of unrewritten arguments, rewrite the arguments and apply.+-- The coercion argument's role matches the role stored in the RewriteM monad.+--+-- The bang patterns used here were observed to improve performance. If you+-- wish to remove them, be sure to check for regeressions in allocations.+rewrite_app_ty_args :: Xi -> Coercion -> [Type] -> RewriteM (Xi, Coercion)+rewrite_app_ty_args fun_xi fun_co []+ -- this will be a common case when called from rewrite_fam_app, so shortcut+ = return (fun_xi, fun_co)+rewrite_app_ty_args fun_xi fun_co arg_tys+ = do { (xi, co, kind_co) <- case tcSplitTyConApp_maybe fun_xi of+ Just (tc, xis) ->+ do { let tc_roles = tyConRolesRepresentational tc+ arg_roles = dropList xis tc_roles+ ; (arg_xis, arg_cos, kind_co)+ <- rewrite_vector (tcTypeKind fun_xi) arg_roles arg_tys++ -- Here, we have fun_co :: T xi1 xi2 ~ ty+ -- and we need to apply fun_co to the arg_cos. The problem is+ -- that using mkAppCo is wrong because that function expects+ -- its second coercion to be Nominal, and the arg_cos might+ -- not be. The solution is to use transitivity:+ -- T <xi1> <xi2> arg_cos ;; fun_co <arg_tys>+ ; eq_rel <- getEqRel+ ; let app_xi = mkTyConApp tc (xis ++ arg_xis)+ app_co = case eq_rel of+ NomEq -> mkAppCos fun_co arg_cos+ ReprEq -> mkTcTyConAppCo Representational tc+ (zipWith mkReflCo tc_roles xis ++ arg_cos)+ `mkTcTransCo`+ mkAppCos fun_co (map mkNomReflCo arg_tys)+ ; return (app_xi, app_co, kind_co) }+ Nothing ->+ do { (arg_xis, arg_cos, kind_co)+ <- rewrite_vector (tcTypeKind fun_xi) (repeat Nominal) arg_tys+ ; let arg_xi = mkAppTys fun_xi arg_xis+ arg_co = mkAppCos fun_co arg_cos+ ; return (arg_xi, arg_co, kind_co) }++ ; role <- getRole+ ; return (homogenise_result xi co role kind_co) }++rewrite_ty_con_app :: TyCon -> [TcType] -> RewriteM (Xi, Coercion)+rewrite_ty_con_app tc tys+ = do { role <- getRole+ ; let m_roles | Nominal <- role = Nothing+ | otherwise = Just $ tyConRolesX role tc+ ; (xis, cos, kind_co) <- rewrite_args_tc tc m_roles tys+ ; let tyconapp_xi = mkTyConApp tc xis+ tyconapp_co = mkTyConAppCo role tc cos+ ; return (homogenise_result tyconapp_xi tyconapp_co role kind_co) }++-- Make the result of rewriting homogeneous (Note [Rewriting] (F2))+homogenise_result :: Xi -- a rewritten type+ -> Coercion -- :: xi ~r original ty+ -> Role -- r+ -> MCoercionN -- kind_co :: tcTypeKind(xi) ~N tcTypeKind(ty)+ -> (Xi, Coercion) -- (xi |> kind_co, (xi |> kind_co)+ -- ~r original ty)+homogenise_result xi co _ MRefl = (xi, co)+homogenise_result xi co r mco@(MCo kind_co)+ = (xi `mkCastTy` kind_co, (mkSymCo $ GRefl r xi mco) `mkTransCo` co)+{-# INLINE homogenise_result #-}++-- Rewrite a vector (list of arguments).+rewrite_vector :: Kind -- of the function being applied to these arguments+ -> [Role] -- If we're rewrite w.r.t. ReprEq, what roles do the+ -- args have?+ -> [Type] -- the args to rewrite+ -> RewriteM ([Xi], [Coercion], MCoercionN)+rewrite_vector ki roles tys+ = do { eq_rel <- getEqRel+ ; case eq_rel of+ NomEq -> rewrite_args bndrs+ any_named_bndrs+ inner_ki+ fvs+ Nothing+ tys+ ReprEq -> rewrite_args bndrs+ any_named_bndrs+ inner_ki+ fvs+ (Just roles)+ tys+ }+ where+ (bndrs, inner_ki, any_named_bndrs) = split_pi_tys' ki -- "RAE" fix+ fvs = tyCoVarsOfType ki+{-# INLINE rewrite_vector #-}++{-+Note [Rewriting synonyms]+~~~~~~~~~~~~~~~~~~~~~~~~~~+Not expanding synonyms aggressively improves error messages, and+keeps types smaller. But we need to take care.++Suppose+ type Syn a = Int+ type instance F Bool = Syn (F Bool)+ [G] F Bool ~ Syn (F Bool)++If we don't expand the synonym, we'll get a spurious occurs-check+failure. This is normally what occCheckExpand takes care of, but+the LHS is a type family application, and occCheckExpand (already+complex enough as it is) does not know how to expand to avoid+a type family application.++In addition, expanding the forgetful synonym like this+will generally yield a *smaller* type. To wit, if we spot+S ( ... F tys ... ), where S is forgetful, we don't want to bother+doing hard work simplifying (F tys). We thus expand forgetful+synonyms, but not others.++isForgetfulSynTyCon returns True more often than it needs to, so+we err on the side of more expansion.++We also, of course, must expand type synonyms that mention type families,+so those families can get reduced.++************************************************************************+* *+ Rewriting a type-family application+* *+************************************************************************++Note [How to normalise a family application]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Given an exactly saturated family application, how should we normalise it?+This Note spells out the algorithm and its reasoning.++STEP 1. Try the famapp-cache. If we get a cache hit, jump to FINISH.++STEP 2. Try top-level instances. Note that we haven't simplified the arguments+ yet. Example:+ type instance F (Maybe a) = Int+ target: F (Maybe (G Bool))+ Instead of first trying to simplify (G Bool), we use the instance first. This+ avoids the work of simplifying G Bool.++ If an instance is found, jump to FINISH.++STEP 3. Rewrite all arguments. This might expose more information so that we+ can use a top-level instance.++ Continue to the next step.++STEP 4. Try the inerts. Note that we try the inerts *after* rewriting the+ arguments, because the inerts will have rewritten LHSs.++ If an inert is found, jump to FINISH.++STEP 5. Try the famapp-cache again. Now that we've revealed more information+ in the arguments, the cache might be helpful.++ If we get a cache hit, jump to FINISH.++STEP 6. Try top-level instances, which might trigger now that we know more+ about the argumnents.++ If an instance is found, jump to FINISH.++STEP 7. No progress to be made. Return what we have. (Do not do FINISH.)++FINISH 1. We've made a reduction, but the new type may still have more+ work to do. So rewrite the new type.++FINISH 2. Add the result to the famapp-cache, connecting the type we started+ with to the one we ended with.++Because STEP 1/2 and STEP 5/6 happen the same way, they are abstracted into+try_to_reduce.++FINISH is naturally implemented in `finish`. But, Note [rewrite_exact_fam_app performance]+tells us that we should not add to the famapp-cache after STEP 1/2. So `finish`+is inlined in that case, and only FINISH 1 is performed.++-}++rewrite_fam_app :: TyCon -> [TcType] -> RewriteM (Xi, Coercion)+ -- rewrite_fam_app can be over-saturated+ -- rewrite_exact_fam_app lifts out the application to top level+ -- Postcondition: Coercion :: Xi ~ F tys+rewrite_fam_app tc tys -- Can be over-saturated+ = ASSERT2( tys `lengthAtLeast` tyConArity tc+ , ppr tc $$ ppr (tyConArity tc) $$ ppr tys)++ -- Type functions are saturated+ -- The type function might be *over* saturated+ -- in which case the remaining arguments should+ -- be dealt with by AppTys+ do { let (tys1, tys_rest) = splitAt (tyConArity tc) tys+ ; (xi1, co1) <- rewrite_exact_fam_app tc tys1+ -- co1 :: xi1 ~ F tys1++ ; rewrite_app_ty_args xi1 co1 tys_rest }++-- the [TcType] exactly saturate the TyCon+-- See Note [How to normalise a family application]+rewrite_exact_fam_app :: TyCon -> [TcType] -> RewriteM (Xi, Coercion)+rewrite_exact_fam_app tc tys+ = do { checkStackDepth (mkTyConApp tc tys)++ -- STEP 1/2. Try to reduce without reducing arguments first.+ ; result1 <- try_to_reduce tc tys+ ; case result1 of+ -- Don't use the cache;+ -- See Note [rewrite_exact_fam_app performance]+ { Just (co, xi) -> finish False (xi, co)+ ; Nothing ->++ -- That didn't work. So reduce the arguments, in STEP 3.+ do { eq_rel <- getEqRel+ -- checking eq_rel == NomEq saves ~0.5% in T9872a+ ; (xis, cos, kind_co) <- if eq_rel == NomEq+ then rewrite_args_tc tc Nothing tys+ else setEqRel NomEq $+ rewrite_args_tc tc Nothing tys+ -- kind_co :: tcTypeKind(F xis) ~N tcTypeKind(F tys)++ ; let role = eqRelRole eq_rel+ args_co = mkTyConAppCo role tc cos+ -- args_co :: F xis ~r F tys++ homogenise :: TcType -> TcCoercion -> (TcType, TcCoercion)+ -- in (xi', co') = homogenise xi co+ -- assume co :: xi ~r F xis, co is homogeneous+ -- then xi' :: tcTypeKind(F tys)+ -- and co' :: xi' ~r F tys, which is homogeneous+ homogenise xi co = homogenise_result xi (co `mkTcTransCo` args_co) role kind_co++ -- STEP 4: try the inerts+ ; result2 <- liftTcS $ lookupFamAppInert tc xis+ ; flavour <- getFlavour+ ; case result2 of+ { Just (co, xi, fr@(_, inert_eq_rel))+ -- co :: F xis ~ir xi++ | fr `eqCanRewriteFR` (flavour, eq_rel) ->+ do { traceRewriteM "rewrite family application with inert"+ (ppr tc <+> ppr xis $$ ppr xi)+ ; finish True (homogenise xi downgraded_co) }+ -- this will sometimes duplicate an inert in the cache,+ -- but avoiding doing so had no impact on performance, and+ -- it seems easier not to weed out that special case+ where+ inert_role = eqRelRole inert_eq_rel+ role = eqRelRole eq_rel+ downgraded_co = tcDowngradeRole role inert_role (mkTcSymCo co)+ -- downgraded_co :: xi ~r F xis++ ; _ ->++ -- inert didn't work. Try to reduce again, in STEP 5/6.+ do { result3 <- try_to_reduce tc xis+ ; case result3 of+ Just (co, xi) -> finish True (homogenise xi co)+ Nothing -> -- we have made no progress at all: STEP 7.+ return (homogenise reduced (mkTcReflCo role reduced))+ where+ reduced = mkTyConApp tc xis }}}}}+ where+ -- call this if the above attempts made progress.+ -- This recursively rewrites the result and then adds to the cache+ finish :: Bool -- add to the cache?+ -> (Xi, Coercion) -> RewriteM (Xi, Coercion)+ finish use_cache (xi, co)+ = do { -- rewrite the result: FINISH 1+ (fully, fully_co) <- bumpDepth $ rewrite_one xi+ ; let final_co = fully_co `mkTcTransCo` co+ ; eq_rel <- getEqRel+ ; flavour <- getFlavour++ -- extend the cache: FINISH 2+ ; when (use_cache && eq_rel == NomEq && flavour /= Derived) $+ -- the cache only wants Nominal eqs+ -- and Wanteds can rewrite Deriveds; the cache+ -- has only Givens+ liftTcS $ extendFamAppCache tc tys (final_co, fully)+ ; return (fully, final_co) }+ {-# INLINE finish #-}++-- Returned coercion is output ~r input, where r is the role in the RewriteM monad+-- See Note [How to normalise a family application]+try_to_reduce :: TyCon -> [TcType] -> RewriteM (Maybe (TcCoercion, TcType))+try_to_reduce tc tys+ = do { result <- liftTcS $ firstJustsM [ lookupFamAppCache tc tys -- STEP 5+ , matchFam tc tys ] -- STEP 6+ ; downgrade result }+ where+ -- The result above is always Nominal. We might want a Representational+ -- coercion; this downgrades (and prints, out of convenience).+ downgrade :: Maybe (TcCoercionN, TcType) -> RewriteM (Maybe (TcCoercion, TcType))+ downgrade Nothing = return Nothing+ downgrade result@(Just (co, xi))+ = do { traceRewriteM "Eager T.F. reduction success" $+ vcat [ ppr tc, ppr tys, ppr xi+ , ppr co <+> dcolon <+> ppr (coercionKind co)+ ]+ ; eq_rel <- getEqRel+ -- manually doing it this way avoids allocation in the vastly+ -- common NomEq case+ ; case eq_rel of+ NomEq -> return result+ ReprEq -> return (Just (mkSubCo co, xi)) }++{-+************************************************************************+* *+ Rewriting a type variable+* *+********************************************************************* -}++-- | The result of rewriting a tyvar "one step".+data RewriteTvResult+ = RTRNotFollowed+ -- ^ The inert set doesn't make the tyvar equal to anything else++ | RTRFollowed TcType Coercion+ -- ^ The tyvar rewrites to a not-necessarily rewritten other type.+ -- co :: new type ~r old type, where the role is determined by+ -- the RewriteEnv+ --+ -- With Quick Look, the returned TcType can be a polytype;+ -- that is, in the constraint solver, a unification variable+ -- can contain a polytype. See GHC.Tc.Gen.App+ -- Note [Instantiation variables are short lived]++rewriteTyVar :: TyVar -> RewriteM (Xi, Coercion)+rewriteTyVar tv+ = do { mb_yes <- rewrite_tyvar1 tv+ ; case mb_yes of+ RTRFollowed ty1 co1 -- Recur+ -> do { (ty2, co2) <- rewrite_one ty1+ -- ; traceRewriteM "rewriteTyVar2" (ppr tv $$ ppr ty2)+ ; return (ty2, co2 `mkTransCo` co1) }++ RTRNotFollowed -- Done, but make sure the kind is zonked+ -- Note [Rewriting] invariant (F0) and (F1)+ -> do { tv' <- liftTcS $ updateTyVarKindM zonkTcType tv+ ; role <- getRole+ ; let ty' = mkTyVarTy tv'+ ; return (ty', mkTcReflCo role ty') } }++rewrite_tyvar1 :: TcTyVar -> RewriteM RewriteTvResult+-- "Rewriting" a type variable means to apply the substitution to it+-- Specifically, look up the tyvar in+-- * the internal MetaTyVar box+-- * the inerts+-- See also the documentation for RewriteTvResult++rewrite_tyvar1 tv+ = do { mb_ty <- liftTcS $ isFilledMetaTyVar_maybe tv+ ; case mb_ty of+ Just ty -> do { traceRewriteM "Following filled tyvar"+ (ppr tv <+> equals <+> ppr ty)+ ; role <- getRole+ ; return (RTRFollowed ty (mkReflCo role ty)) } ;+ Nothing -> do { traceRewriteM "Unfilled tyvar" (pprTyVar tv)+ ; fr <- getFlavourRole+ ; rewrite_tyvar2 tv fr } }++rewrite_tyvar2 :: TcTyVar -> CtFlavourRole -> RewriteM RewriteTvResult+-- The tyvar is not a filled-in meta-tyvar+-- Try in the inert equalities+-- See Definition [Applying a generalised substitution] in GHC.Tc.Solver.Monad+-- See Note [Stability of rewriting] in GHC.Tc.Solver.Monad++rewrite_tyvar2 tv fr@(_, eq_rel)+ = do { ieqs <- liftTcS $ getInertEqs+ ; case lookupDVarEnv ieqs tv of+ Just (EqualCtList (ct :| _)) -- If the first doesn't work,+ -- the subsequent ones won't either+ | CEqCan { cc_ev = ctev, cc_lhs = TyVarLHS tv+ , cc_rhs = rhs_ty, cc_eq_rel = ct_eq_rel } <- ct+ , let ct_fr = (ctEvFlavour ctev, ct_eq_rel)+ , ct_fr `eqCanRewriteFR` fr -- This is THE key call of eqCanRewriteFR+ -> do { traceRewriteM "Following inert tyvar"+ (ppr tv <+>+ equals <+>+ ppr rhs_ty $$ ppr ctev)+ ; let rewrite_co1 = mkSymCo (ctEvCoercion ctev)+ rewrite_co = case (ct_eq_rel, eq_rel) of+ (ReprEq, _rel) -> ASSERT( _rel == ReprEq )+ -- if this ASSERT fails, then+ -- eqCanRewriteFR answered incorrectly+ rewrite_co1+ (NomEq, NomEq) -> rewrite_co1+ (NomEq, ReprEq) -> mkSubCo rewrite_co1++ ; return (RTRFollowed rhs_ty rewrite_co) }+ -- NB: ct is Derived then fmode must be also, hence+ -- we are not going to touch the returned coercion+ -- so ctEvCoercion is fine.++ _other -> return RTRNotFollowed }++{-+Note [An alternative story for the inert substitution]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+(This entire note is just background, left here in case we ever want+ to return the previous state of affairs)++We used (GHC 7.8) to have this story for the inert substitution inert_eqs++ * 'a' is not in fvs(ty)+ * They are *inert* in the weaker sense that there is no infinite chain of+ (i1 `eqCanRewrite` i2), (i2 `eqCanRewrite` i3), etc++This means that rewriting must be recursive, but it does allow+ [G] a ~ [b]+ [G] b ~ Maybe c++This avoids "saturating" the Givens, which can save a modest amount of work.+It is easy to implement, in GHC.Tc.Solver.Interact.kick_out, by only kicking out an inert+only if (a) the work item can rewrite the inert AND+ (b) the inert cannot rewrite the work item++This is significantly harder to think about. It can save a LOT of work+in occurs-check cases, but we don't care about them much. #5837+is an example, but it causes trouble only with the old (pre-Fall 2020)+rewriting story. It is unclear if there is any gain w.r.t. to+the new story.++-}++--------------------------------------+-- Utilities++-- | Like 'splitPiTys'' but comes with a 'Bool' which is 'True' iff there is at+-- least one named binder.+split_pi_tys' :: Type -> ([TyCoBinder], Type, Bool)+split_pi_tys' ty = split ty ty+ where+ -- put common cases first+ split _ (ForAllTy b res) = let (bs, ty, _) = split res res+ in (Named b : bs, ty, True)+ split _ (FunTy { ft_af = af, ft_mult = w, ft_arg = arg, ft_res = res })+ = let (bs, ty, named) = split res res+ in (Anon af (mkScaled w arg) : bs, ty, named)++ split orig_ty ty | Just ty' <- coreView ty = split orig_ty ty'+ split orig_ty _ = ([], orig_ty, False)+{-# INLINE split_pi_tys' #-}++-- | Like 'tyConBindersTyCoBinders' but you also get a 'Bool' which is true iff+-- there is at least one named binder.+ty_con_binders_ty_binders' :: [TyConBinder] -> ([TyCoBinder], Bool)+ty_con_binders_ty_binders' = foldr go ([], False)+ where+ go (Bndr tv (NamedTCB vis)) (bndrs, _)+ = (Named (Bndr tv vis) : bndrs, True)+ go (Bndr tv (AnonTCB af)) (bndrs, n)+ = (Anon af (tymult (tyVarKind tv)) : bndrs, n)+ {-# INLINE go #-}+{-# INLINE ty_con_binders_ty_binders' #-}
compiler/GHC/Tc/TyCl.hs view
@@ -17,7 +17,8 @@ -- Functions used by GHC.Tc.TyCl.Instance to check -- data/type family instance declarations- kcConDecls, tcConDecls, dataDeclChecks, checkValidTyCon,+ kcConDecls, tcConDecls, DataDeclInfo(..),+ dataDeclChecks, checkValidTyCon, tcFamTyPats, tcTyFamInstEqn, tcAddTyFamInstCtxt, tcMkDataFamInstCtxt, tcAddDataFamInstCtxt, unravelFamInstPats, addConsistencyConstraints,@@ -38,7 +39,7 @@ , reportUnsolvedEqualities ) import GHC.Tc.Utils.Monad import GHC.Tc.Utils.Env-import GHC.Tc.Utils.Unify( emitResidualTvConstraint )+import GHC.Tc.Utils.Unify( unifyType, emitResidualTvConstraint ) import GHC.Tc.Types.Constraint( emptyWC ) import GHC.Tc.Validity import GHC.Tc.Utils.Zonk@@ -130,7 +131,7 @@ Role inference potentially depends on the types of all of the datacons declared in a mutually recursive group. The validity of a role annotation, in turn, depends on the result of role inference. Because the types of datacons might-be ill-formed (see #7175 and Note [Checking GADT return types]) we must check+be ill-formed (see #7175 and Note [rejigConRes]) we must check *all* the tycons in a group for validity before checking *any* of the roles. Thus, we take two passes over the resulting tycons, first checking for general validity and then checking for valid role annotations.@@ -1529,27 +1530,16 @@ -- result kind signature have already been dealt with -- by inferInitialKind, so we can ignore them here. -kcTyClDecl (DataDecl { tcdLName = (L _ name)- , tcdDataDefn = defn }) tyCon- | HsDataDefn { dd_cons = cons@((L _ (ConDeclGADT {})) : _)- , dd_ctxt = (L _ [])- , dd_ND = new_or_data } <- defn- = -- See Note [Implementation of UnliftedNewtypes] STEP 2- kcConDecls new_or_data (tyConResKind tyCon) cons-- -- hs_tvs and dd_kindSig already dealt with in inferInitialKind- -- This must be a GADT-style decl,- -- (see invariants of DataDefn declaration)- -- so (a) we don't need to bring the hs_tvs into scope, because the- -- ConDecls bind all their own variables- -- (b) dd_ctxt is not allowed for GADT-style decls, so we can ignore it-- | HsDataDefn { dd_ctxt = ctxt- , dd_cons = cons- , dd_ND = new_or_data } <- defn+kcTyClDecl (DataDecl { tcdLName = (L _ name), tcdDataDefn = defn }) tycon+ | HsDataDefn { dd_ctxt = ctxt, dd_cons = cons, dd_ND = new_or_data } <- defn = bindTyClTyVars name $ \ _ _ _ ->- do { _ <- tcHsContext ctxt- ; kcConDecls new_or_data (tyConResKind tyCon) cons+ -- NB: binding these tyvars isn't necessary for GADTs, but it does no+ -- harm. For GADTs, each data con brings its own tyvars into scope,+ -- and the ones from this bindTyClTyVars are either not mentioned or+ -- (conceivably) shadowed.+ do { traceTc "kcTyClDecl" (ppr tycon $$ ppr (tyConTyVars tycon) $$ ppr (tyConResKind tycon))+ ; _ <- tcHsContext ctxt+ ; kcConDecls new_or_data (tyConResKind tycon) cons } kcTyClDecl (SynDecl { tcdLName = L _ name, tcdRhs = rhs }) _tycon@@ -1585,14 +1575,13 @@ { let exp_kind = getArgExpKind new_or_data res_kind ; forM_ arg_tys (\(HsScaled mult ty) -> do _ <- tcCheckLHsType (getBangType ty) exp_kind tcMult mult)- -- See Note [Implementation of UnliftedNewtypes], STEP 2 } -- Kind-check the types of arguments to a Haskell98 data constructor. kcConH98Args :: NewOrData -> Kind -> HsConDeclH98Details GhcRn -> TcM () kcConH98Args new_or_data res_kind con_args = case con_args of- PrefixCon tys -> kcConArgTys new_or_data res_kind tys+ PrefixCon _ tys -> kcConArgTys new_or_data res_kind tys InfixCon ty1 ty2 -> kcConArgTys new_or_data res_kind [ty1, ty2] RecCon (L _ flds) -> kcConArgTys new_or_data res_kind $ map (hsLinear . cd_fld_type . unLoc) flds@@ -1606,13 +1595,12 @@ kcConDecls :: NewOrData -> Kind -- The result kind signature+ -- Used only in H98 case -> [LConDecl GhcRn] -- The data constructors -> TcM ()-kcConDecls new_or_data res_kind cons- = mapM_ (wrapLocM_ (kcConDecl new_or_data final_res_kind)) cons- where- (_, final_res_kind) = splitPiTys res_kind- -- See Note [kcConDecls result kind]+-- See Note [kcConDecls: kind-checking data type decls]+kcConDecls new_or_data tc_res_kind cons+ = mapM_ (wrapLocM_ (kcConDecl new_or_data tc_res_kind)) cons -- Kind check a data constructor. In additional to the data constructor, -- we also need to know about whether or not its corresponding type was@@ -1623,82 +1611,77 @@ -> Kind -- Result kind of the type constructor -- Usually Type but can be TYPE UnliftedRep -- or even TYPE r, in the case of unlifted newtype+ -- Used only in H98 case -> ConDecl GhcRn -> TcM ()-kcConDecl new_or_data res_kind (ConDeclH98+kcConDecl new_or_data tc_res_kind (ConDeclH98 { con_name = name, con_ex_tvs = ex_tvs , con_mb_cxt = ex_ctxt, con_args = args })- = addErrCtxt (dataConCtxtName [name]) $+ = addErrCtxt (dataConCtxt [name]) $ discardResult $ bindExplicitTKBndrs_Tv ex_tvs $ do { _ <- tcHsMbContext ex_ctxt- ; kcConH98Args new_or_data res_kind args+ ; kcConH98Args new_or_data tc_res_kind args -- We don't need to check the telescope here, -- because that's done in tcConDecl } -kcConDecl new_or_data res_kind (ConDeclGADT+kcConDecl new_or_data+ _tc_res_kind -- Not used in GADT case (and doesn't make sense)+ (ConDeclGADT { con_names = names, con_bndrs = L _ outer_bndrs, con_mb_cxt = cxt , con_g_args = args, con_res_ty = res_ty })- = -- Even though the GADT-style data constructor's type is closed,- -- we must still kind-check the type, because that may influence- -- the inferred kind of the /type/ constructor. Example:- -- data T f a where- -- MkT :: f a -> T f a- -- If we don't look at MkT we won't get the correct kind- -- for the type constructor T- addErrCtxt (dataConCtxtName names) $+ = -- See Note [kcConDecls: kind-checking data type decls]+ addErrCtxt (dataConCtxt names) $ discardResult $ bindOuterSigTKBndrs_Tv outer_bndrs $- -- Why "_Tv"? See Note [Kind-checking for GADTs]+ -- Why "_Tv"? See Note [Using TyVarTvs for kind-checking GADTs] do { _ <- tcHsMbContext cxt- ; kcConGADTArgs new_or_data res_kind args- ; _ <- tcHsOpenType res_ty+ ; traceTc "kcConDecl:GADT {" (ppr names $$ ppr res_ty)+ ; con_res_kind <- newOpenTypeKind+ ; _ <- tcCheckLHsType res_ty (TheKind con_res_kind)+ ; kcConGADTArgs new_or_data con_res_kind args+ ; traceTc "kcConDecl:GADT }" (ppr names $$ ppr con_res_kind) ; return () } -{- Note [kcConDecls result kind]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We might have e.g.- data T a :: Type -> Type where ...-or- newtype instance N a :: Type -> Type where ..-in which case, the 'res_kind' passed to kcConDecls will be- Type->Type--We must look past those arrows, or even foralls, to the Type in the-corner, to pass to kcConDecl c.f. #16828. Hence the splitPiTys here.--I am a bit concerned about tycons with a declaration like- data T a :: Type -> forall k. k -> Type where ...--It does not have a CUSK, so kcInferDeclHeader will make a TcTyCon-with tyConResKind of Type -> forall k. k -> Type. Even that is fine:-the splitPiTys will look past the forall. But I'm bothered about-what if the type "in the corner" mentions k? This is incredibly-obscure but something like this could be bad:- data T a :: Type -> foral k. k -> TYPE (F k) where ...+{- Note [kcConDecls: kind-checking data type decls]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+kcConDecls is used when we are inferring the kind of the type+constructor in a data type declaration. E.g.+ data T f a = MkT (f a)+we want to infer the kind of 'f' and 'a'. The basic plan is described+in Note [Inferring kinds for type declarations]; here we are doing Step 2. -I bet we are not quite right here, but my brain suffered a buffer-overflow and I thought it best to nail the common cases right now.+In the GADT case we may have this:+ data T f a where+ MkT :: forall g b. g b -> T g b -Note [Recursion and promoting data constructors]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We don't want to allow promotion in a strongly connected component-when kind checking.+Notice that the variables f,a, and g,b are quite distinct.+Nevertheless, the type signature for MkT must still influence the kind+T which is (remember Step 1) something like+ T :: kappa1 -> kappa2 -> Type+Otherwise we'd infer the bogus kind+ T :: forall k1 k2. k1 -> k2 -> Type. -Consider:- data T f = K (f (K Any))+The type signature for MkT influences the kind of T simply by+kind-checking the result type (T g b), which will force 'f' and 'g' to+have the same kinds. This is the call to+ tcCheckLHsType res_ty (TheKind con_res_kind)+Because this is the result type of an arrow, we know the kind must be+of form (TYPE rr), and we get better error messages if we enforce that+here (e.g. test gadt10). -When kind checking the `data T' declaration the local env contains the-mappings:- T -> ATcTyCon <some initial kind>- K -> APromotionErr+For unlifted newtypes only, we must ensure that the argument kind+and result kind are the same:+* In the H98 case, we need the result kind of the TyCon, to unify with+ the argument kind. -APromotionErr is only used for DataCons, and only used during type checking-in tcTyClGroup.+* In GADT syntax, this unification happens via the result kind passed+ to kcConGADTArgs. The tycon's result kind is not used at all in the+ GADT case. -Note [Kind-checking for GADTs]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Note [Using TyVarTvs for kind-checking GADTs]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider data Proxy a where@@ -1708,26 +1691,27 @@ It seems reasonable that this should be accepted. But something very strange is going on here: when we're kind-checking this declaration, we need to unify the kind of `a` with k and j -- even though k and j's scopes are local to the type of-MkProxy{1,2}. The best approach we've come up with is to use TyVarTvs during-the kind-checking pass. First off, note that it's OK if the kind-checking pass-is too permissive: we'll snag the problems in the type-checking pass later.-(This extra permissiveness might happen with something like+MkProxy{1,2}. +In effect, we are simply gathering constraints on the shape of Proxy's+kind, with no skolemisation or implication constraints involved at all.++The best approach we've come up with is to use TyVarTvs during the+kind-checking pass, rather than ordinary skolems. This is why we use+the "_Tv" variant, bindOuterSigTKBndrs_Tv.++Our only goal is to gather constraints on the kind of the type constructor;+we do not certify that the data declaration is well-kinded. For example:+ data SameKind :: k -> k -> Type data Bad a where MkBad :: forall k1 k2 (a :: k1) (b :: k2). Bad (SameKind a b) -which would be accepted if k1 and k2 were TyVarTvs. This is correctly rejected-in the second pass, though. Test case: polykinds/TyVarTvKinds3)-Recall that the kind-checking pass exists solely to collect constraints-on the kinds and to power unification.--To achieve the use of TyVarTvs, we must be careful to use specialized functions-that produce TyVarTvs, not ordinary skolems. This is why we need-kcExplicitTKBndrs and kcImplicitTKBndrs in GHC.Tc.Gen.HsType, separate from their-tc... variants.+which would be accepted by kcConDecl because k1 and k2 are+TyVarTvs. It is correctly rejected in the second pass, tcConDecl.+(Test case: polykinds/TyVarTvKinds3) -The drawback of this approach is sometimes it will accept a definition that+One drawback of this approach is sometimes it will accept a definition that a (hypothetical) declarative specification would likely reject. As a general rule, we don't want to allow polymorphic recursion without a CUSK. Indeed, the whole point of CUSKs is to allow polymorphic recursion. Yet, the TyVarTvs@@ -1746,6 +1730,23 @@ well-kinded and any rejected definitions would be accepted with a CUSK, and so this wrinkle need not cause anyone to lose sleep. +Note [Recursion and promoting data constructors]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We don't want to allow promotion in a strongly connected component+when kind checking.++Consider:+ data T f = K (f (K Any))++When kind checking the `data T' declaration the local env contains the+mappings:+ T -> ATcTyCon <some initial kind>+ K -> APromotionErr++APromotionErr is only used for DataCons, and only used during type checking+in tcTyClGroup.++ ************************************************************************ * * \subsection{Type checking}@@ -2782,18 +2783,14 @@ ; when (isJust mb_ksig) $ checkTc (kind_signatures) (badSigTyDecl tc_name) - ; tycon <- fixM $ \ tycon -> do+ ; tycon <- fixM $ \ rec_tycon -> do { let final_bndrs = tycon_binders `chkAppend` extra_bndrs- res_ty = mkTyConApp tycon (mkTyVarTys (binderVars final_bndrs)) roles = roles_info tc_name ; data_cons <- tcConDecls- tycon- new_or_data- final_bndrs- final_res_kind- res_ty+ new_or_data DDataType+ rec_tycon final_bndrs final_res_kind cons- ; tc_rhs <- mk_tc_rhs hsc_src tycon data_cons+ ; tc_rhs <- mk_tc_rhs hsc_src rec_tycon data_cons ; tc_rep_nm <- newTyConRepName tc_name ; return (mkAlgTyCon tc_name final_bndrs@@ -3195,36 +3192,51 @@ -- All constructors have same shape ------------------------------------tcConDecls :: KnotTied TyCon -> NewOrData- -> [TyConBinder] -> TcKind -- binders and result kind of tycon- -> KnotTied Type -> [LConDecl GhcRn] -> TcM [DataCon]-tcConDecls rep_tycon new_or_data tmpl_bndrs res_kind res_tmpl+data DataDeclInfo+ = DDataType -- data T a b = T1 a | T2 b+ | DDataInstance -- data instance D [a] = D1 a | D2+ Type -- The header D [a]++mkDDHeaderTy :: DataDeclInfo -> TyCon -> [TyConBinder] -> Type+mkDDHeaderTy dd_info rep_tycon tc_bndrs+ = case dd_info of+ DDataType -> mkTyConApp rep_tycon $+ mkTyVarTys (binderVars tc_bndrs)+ DDataInstance header_ty -> header_ty++tcConDecls :: NewOrData+ -> DataDeclInfo+ -> KnotTied TyCon -- Representation TyCon+ -> [TyConBinder] -- Binders of representation TyCon+ -> TcKind -- Result kind+ -> [LConDecl GhcRn] -> TcM [DataCon]+tcConDecls new_or_data dd_info rep_tycon tmpl_bndrs res_kind = concatMapM $ addLocM $- tcConDecl rep_tycon (mkTyConTagMap rep_tycon)- tmpl_bndrs res_kind res_tmpl new_or_data- -- It's important that we pay for tag allocation here, once per TyCon,- -- See Note [Constructor tag allocation], fixes #14657+ tcConDecl new_or_data dd_info rep_tycon tmpl_bndrs res_kind+ (mkTyConTagMap rep_tycon)+ -- mkTyConTagMap: it's important that we pay for tag allocation here,+ -- once per TyCon. See Note [Constructor tag allocation], fixes #14657 -tcConDecl :: KnotTied TyCon -- Representation tycon. Knot-tied!+tcConDecl :: NewOrData+ -> DataDeclInfo+ -> KnotTied TyCon -- Representation tycon. Knot-tied!+ -> [TyConBinder] -- Binders of representation TyCon+ -> TcKind -- Result kind -> NameEnv ConTag- -> [TyConBinder] -> TcKind -- tycon binders and result kind- -> KnotTied Type- -- Return type template (T tys), where T is the family TyCon- -> NewOrData -> ConDecl GhcRn -> TcM [DataCon] -tcConDecl rep_tycon tag_map tmpl_bndrs res_kind res_tmpl new_or_data+tcConDecl new_or_data dd_info rep_tycon tc_bndrs res_kind tag_map (ConDeclH98 { con_name = lname@(L _ name) , con_ex_tvs = explicit_tkv_nms , con_mb_cxt = hs_ctxt , con_args = hs_args })- = addErrCtxt (dataConCtxtName [lname]) $+ = addErrCtxt (dataConCtxt [lname]) $ do { -- NB: the tyvars from the declaration header are in scope -- Get hold of the existential type variables -- e.g. data T a = forall k (b::k) f. MkT a (f b)- -- Here tmpl_bndrs = {a}+ -- Here tc_bndrs = {a} -- hs_qvars = HsQTvs { hsq_implicit = {k} -- , hsq_explicit = {f,b} } @@ -3242,29 +3254,35 @@ } - ; let tmpl_tvs = binderVars tmpl_bndrs- ; let fake_ty = mkSpecForAllTys tmpl_tvs $+ ; let tc_tvs = binderVars tc_bndrs+ fake_ty = mkSpecForAllTys tc_tvs $ mkInvisForAllTys exp_tvbndrs $ mkPhiTy ctxt $ mkVisFunTys arg_tys $ unitTy -- That type is a lie, of course. (It shouldn't end in ()!) -- And we could construct a proper result type from the info- -- at hand. But the result would mention only the tmpl_tvs,+ -- at hand. But the result would mention only the univ_tvs, -- and so it just creates more work to do it right. Really, -- we're only doing this to find the right kind variables to -- quantify over, and this type is fine for that purpose. - -- exp_tvs have explicit, user-written binding sites+ -- exp_tvbndrs have explicit, user-written binding sites -- the kvs below are those kind variables entirely unmentioned by the user -- and discovered only by generalization ; kvs <- kindGeneralizeAll fake_ty - ; let skol_tvs = kvs ++ tmpl_tvs+ ; let skol_tvs = tc_tvs ++ kvs ++ binderVars exp_tvbndrs ; reportUnsolvedEqualities skol_info skol_tvs tclvl wanted+ -- The skol_info claims that all the variables are bound+ -- by the data constructor decl, whereas actually the+ -- univ_tvs are bound by the data type decl itself. It+ -- would be better to have a doubly-nested implication.+ -- But that just doesn't seem worth it.+ -- See test dependent/should_fail/T13780a - -- Zonk to Types+ -- Zonk to Types ; (ze, qkvs) <- zonkTyBndrs kvs ; (ze, user_qtvbndrs) <- zonkTyVarBindersX ze exp_tvbndrs ; arg_tys <- zonkScaledTcTypesToTypesX ze arg_tys@@ -3272,15 +3290,14 @@ -- Can't print univ_tvs, arg_tys etc, because we are inside the knot here ; traceTc "tcConDecl 2" (ppr name $$ ppr field_lbls)- ; let- univ_tvbs = tyConInvisTVBinders tmpl_bndrs- univ_tvs = binderVars univ_tvbs- ex_tvbs = mkTyVarBinders InferredSpec qkvs ++ user_qtvbndrs- ex_tvs = binderVars ex_tvbs- -- For H98 datatypes, the user-written tyvar binders are precisely- -- the universals followed by the existentials.- -- See Note [DataCon user type variable binders] in GHC.Core.DataCon.- user_tvbs = univ_tvbs ++ ex_tvbs+ ; let univ_tvbs = tyConInvisTVBinders tc_bndrs+ ex_tvbs = mkTyVarBinders InferredSpec qkvs ++ user_qtvbndrs+ ex_tvs = binderVars ex_tvbs+ -- For H98 datatypes, the user-written tyvar binders are precisely+ -- the universals followed by the existentials.+ -- See Note [DataCon user type variable binders] in GHC.Core.DataCon.+ user_tvbs = univ_tvbs ++ ex_tvbs+ user_res_ty = mkDDHeaderTy dd_info rep_tycon tc_bndrs ; traceTc "tcConDecl 2" (ppr name) ; is_infix <- tcConIsInfixH98 name hs_args@@ -3288,9 +3305,9 @@ ; fam_envs <- tcGetFamInstEnvs ; dc <- buildDataCon fam_envs name is_infix rep_nm stricts Nothing field_lbls- univ_tvs ex_tvs user_tvbs+ tc_tvs ex_tvs user_tvbs [{- no eq_preds -}] ctxt arg_tys- res_tmpl rep_tycon tag_map+ user_res_ty rep_tycon tag_map -- NB: we put data_tc, the type constructor gotten from the -- constructor type signature into the data constructor; -- that way checkValidDataCon can complain if it's wrong.@@ -3299,14 +3316,14 @@ where skol_info = DataConSkol name -tcConDecl rep_tycon tag_map tmpl_bndrs _res_kind res_tmpl new_or_data+tcConDecl new_or_data dd_info rep_tycon tc_bndrs _res_kind tag_map -- NB: don't use res_kind here, as it's ill-scoped. Instead, -- we get the res_kind by typechecking the result type. (ConDeclGADT { con_names = names , con_bndrs = L _ outer_hs_bndrs , con_mb_cxt = cxt, con_g_args = hs_args , con_res_ty = hs_res_ty })- = addErrCtxt (dataConCtxtName names) $+ = addErrCtxt (dataConCtxt names) $ do { traceTc "tcConDecl 1 gadt" (ppr names) ; let (L _ name : _) = names @@ -3317,10 +3334,23 @@ ; (res_ty, res_kind) <- tcInferLHsTypeKind hs_res_ty -- See Note [GADT return kinds] + -- For data instances (only), ensure that the return type,+ -- res_ty, is a substitution instance of the header.+ -- See Note [GADT return types]+ ; case dd_info of+ DDataType -> return ()+ DDataInstance hdr_ty ->+ do { (subst, _meta_tvs) <- newMetaTyVars (binderVars tc_bndrs)+ ; let head_shape = substTy subst hdr_ty+ ; discardResult $+ popErrCtxt $ -- Drop dataConCtxt+ addErrCtxt (dataConResCtxt names) $+ unifyType Nothing res_ty head_shape }+ -- See Note [Datatype return kinds] ; let exp_kind = getArgExpKind new_or_data res_kind- ; btys <- tcConGADTArgs exp_kind hs_args+ ; let (arg_tys, stricts) = unzip btys ; field_lbls <- lookupConstructorFields name ; return (ctxt, arg_tys, res_ty, field_lbls, stricts)@@ -3343,9 +3373,10 @@ ; ctxt <- zonkTcTypesToTypesX ze ctxt ; res_ty <- zonkTcTypeToTypeX ze res_ty - ; let (univ_tvs, ex_tvs, tvbndrs', eq_preds, arg_subst)- = rejigConRes tmpl_bndrs res_tmpl tvbndrs res_ty- -- See Note [Checking GADT return types]+ ; let res_tmpl = mkDDHeaderTy dd_info rep_tycon tc_bndrs+ (univ_tvs, ex_tvs, tvbndrs', eq_preds, arg_subst)+ = rejigConRes tc_bndrs res_tmpl tvbndrs res_ty+ -- See Note [rejigConRes] ctxt' = substTys arg_subst ctxt arg_tys' = substScaledTys arg_subst arg_tys@@ -3372,9 +3403,74 @@ where skol_info = DataConSkol (unLoc (head names)) -{- Note [GADT return kinds]+{- Note [GADT return types] ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider+ data family T :: forall k. k -> Type+ data instance T (a :: Type) where+ MkT :: forall b. T b++What kind does `b` have in the signature for MkT?+Since the return type must be an instance of the type in the header,+we must have (b :: Type), but you can't tell that by looking only at+the type of the data constructor; you have to look at the header too.+If you wrote it out fully, it'd look like+ data instance T @Type (a :: Type) where+ MkT :: forall (b::Type). T @Type b++We could reject the program, and expect the user to add kind+annotations to `MkT` to restrict the signature. But an easy and+helpful alternative is this: simply instantiate the type from the+header with fresh unification variables, and unify with the return+type of `MkT`. That will force `b` to have kind `Type`. See #8707+and #14111.++Wrikles+* At first sight it looks as though this would completely subsume the+ return-type check in checkValidDataCon. But it does not. Suppose we+ have+ data instance T [a] where+ MkT :: T (F (Maybe a))++ where F is a type function. Then maybe (F (Maybe a)) evaluates to+ [a], so unifyType will succeed. But we discard the coercion+ returned by unifyType; and we really don't want to accept this+ program. The check in checkValidDataCon will, however, reject it.+ TL;DR: keep the check in checkValidDataCon.++* Consider a data type, rather than a data instance, declaration+ data S a where { MkS :: b -> S [b] }+ In tcConDecl, S is knot-tied, so we don't want to unify (S alpha)+ with (S [b]). To put it another way, unifyType should never see a+ TcTycon. Simple solution: do *not* do the extra unifyType for+ data types (DDataType) only for data instances (DDataInstance); in+ the latter the family constructor is not knot-tied so there is no+ problem.++* Consider this (from an earlier form of GHC itself):++ data Pass = Parsed | ...+ data GhcPass (c :: Pass) where+ GhcPs :: GhcPs+ ...+ type GhcPs = GhcPass 'Parsed++ Now GhcPs and GhcPass are mutually recursive. If we did unifyType+ for datatypes like GhcPass, we would not be able to expand the type+ synonym (it'd still be a TcTyCon). So again, we don't do unifyType+ for data types; we leave it to checkValidDataCon.++ We /do/ perform the unifyType for data /instances/, but a data+ instance doesn't declare a new (user-visible) type constructor, so+ there is no mutual recursion with type synonyms to worry about.+ All good.++ TL;DR we do support mutual recursion between type synonyms and+ data type/instance declarations, as above.++Note [GADT return kinds]+~~~~~~~~~~~~~~~~~~~~~~~~+Consider type family Star where Star = Type data T :: Type where MkT :: Int -> T@@ -3423,7 +3519,7 @@ -- might have a specific kind -> HsConDeclH98Details GhcRn -> TcM [(Scaled TcType, HsSrcBang)]-tcConH98Args exp_kind (PrefixCon btys)+tcConH98Args exp_kind (PrefixCon _ btys) = mapM (tcConArg exp_kind) btys tcConH98Args exp_kind (InfixCon bty1 bty2) = do { bty1' <- tcConArg exp_kind bty1@@ -3496,8 +3592,8 @@ (:--:) :: t1 -> t2 -> T Int -Note [Checking GADT return types]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Note [rejigConRes]+~~~~~~~~~~~~~~~~~~ There is a delicacy around checking the return types of a datacon. The central problem is dealing with a declaration like @@ -3532,9 +3628,9 @@ -- TI :: forall b1 c1. (b1 ~ c1) => b1 -> :R7T b1 c1 -- In this case orig_res_ty = T (e,e) -rejigConRes :: [KnotTied TyConBinder] -> KnotTied Type -- Template for result type; e.g.- -- data instance T [a] b c ...- -- gives template ([a,b,c], T [a] b c)+rejigConRes :: [KnotTied TyConBinder] -- Template for result type; e.g.+ -> KnotTied Type -- data instance T [a] b c ...+ -- gives template ([a,b,c], T [a] b c) -> [InvisTVBinder] -- The constructor's type variables (both inferred and user-written) -> KnotTied Type -- res_ty -> ([TyVar], -- Universal@@ -3546,10 +3642,10 @@ -- We don't check that the TyCon given in the ResTy is -- the same as the parent tycon, because checkValidDataCon will do it -- NB: All arguments may potentially be knot-tied-rejigConRes tmpl_bndrs res_tmpl dc_tvbndrs res_ty+rejigConRes tc_tvbndrs res_tmpl dc_tvbndrs res_ty -- E.g. data T [a] b c where -- MkT :: forall x y z. T [(x,y)] z z- -- The {a,b,c} are the tmpl_tvs, and the {x,y,z} are the dc_tvs+ -- The {a,b,c} are the tc_tvs, and the {x,y,z} are the dc_tvs -- (NB: unlike the H98 case, the dc_tvs are not all existential) -- Then we generate -- Univ tyvars Eq-spec@@ -3564,7 +3660,7 @@ -- , [], [x,y,z] -- , [a~(x,y),b~z], <arg-subst> ) | Just subst <- tcMatchTy res_tmpl res_ty- = let (univ_tvs, raw_eqs, kind_subst) = mkGADTVars tmpl_tvs dc_tvs subst+ = let (univ_tvs, raw_eqs, kind_subst) = mkGADTVars tc_tvs dc_tvs subst raw_ex_tvs = dc_tvs `minusList` univ_tvs (arg_subst, substed_ex_tvs) = substTyVarBndrs kind_subst raw_ex_tvs @@ -3590,11 +3686,11 @@ -- we must do *something*, not just crash. So we do something simple -- albeit bogus, relying on checkValidDataCon to check the -- bad-result-type error before seeing that the other fields look odd- -- See Note [Checking GADT return types]- = (tmpl_tvs, dc_tvs `minusList` tmpl_tvs, dc_tvbndrs, [], emptyTCvSubst)+ -- See Note [rejigConRes]+ = (tc_tvs, dc_tvs `minusList` tc_tvs, dc_tvbndrs, [], emptyTCvSubst) where- dc_tvs = binderVars dc_tvbndrs- tmpl_tvs = binderVars tmpl_bndrs+ dc_tvs = binderVars dc_tvbndrs+ tc_tvs = binderVars tc_tvbndrs {- Note [mkGADTVars] ~~~~~~~~~~~~~~~~~~~~@@ -3634,7 +3730,7 @@ We start off by matching (T k1 k2 a b) with (T x1 * (Proxy x1 y, z) z). We know this match will succeed because of the validity check (actually done-later, but laziness saves us -- see Note [Checking GADT return types]).+later, but laziness saves us -- see Note [rejigConRes]). Thus, we get subst := { k1 |-> x1, k2 |-> *, a |-> (Proxy x1 y, z), b |-> z }@@ -4056,9 +4152,8 @@ (sep [text "Use of partial record field selector" <> colon, nest 2 $ quotes (ppr occ_name)]) where- sel_name = flSelector fld- loc = getSrcSpan sel_name- occ_name = getOccName sel_name+ loc = getSrcSpan (flSelector fld)+ occ_name = occName fld (cons_with_field, cons_without_field) = partition has_field all_cons has_field con = fld `elem` (dataConFieldLabels con)@@ -4081,15 +4176,9 @@ ------------------------------- checkValidDataCon :: DynFlags -> Bool -> TyCon -> DataCon -> TcM () checkValidDataCon dflags existential_ok tc con- = setSrcSpan (getSrcSpan con) $- addErrCtxt (dataConCtxt con) $- do { -- Check that the return type of the data constructor- -- matches the type constructor; eg reject this:- -- data T a where { MkT :: Bogus a }- -- It's important to do this first:- -- see Note [Checking GADT return types]- -- and c.f. Note [Check role annotations in a second pass]- let tc_tvs = tyConTyVars tc+ = setSrcSpan con_loc $+ addErrCtxt (dataConCtxt [L con_loc con_name]) $+ do { let tc_tvs = tyConTyVars tc res_ty_tmpl = mkFamilyTyConApp tc (mkTyVarTys tc_tvs) orig_res_ty = dataConOrigResTy con ; traceTc "checkValidDataCon" (vcat@@ -4098,6 +4187,18 @@ , ppr orig_res_ty <+> dcolon <+> ppr (tcTypeKind orig_res_ty)]) + -- Check that the return type of the data constructor+ -- matches the type constructor; eg reject this:+ -- data T a where { MkT :: Bogus a }+ -- It's important to do this first:+ -- see Note [rejigCon+ -- and c.f. Note [Check role annotations in a second pass]++ -- Check that the return type of the data constructor is an instance+ -- of the header of the header of data decl. This checks for+ -- data T a where { MkT :: S a }+ -- data instance D [a] where { MkD :: D (Maybe b) }+ -- see Note [GADT return types] ; checkTc (isJust (tcMatchTyKi res_ty_tmpl orig_res_ty)) (badDataConTyCon con res_ty_tmpl) -- Note that checkTc aborts if it finds an error. This is@@ -4205,7 +4306,9 @@ Just (f, _) -> ppr (tyConBinders f) ] } where- ctxt = ConArgCtxt (dataConName con)+ con_name = dataConName con+ con_loc = nameSrcSpan con_name+ ctxt = ConArgCtxt con_name is_strict = \case NoSrcStrict -> xopt LangExt.StrictData dflags bang -> isSrcStrict bang@@ -4869,14 +4972,17 @@ = sep [text "Constructors" <+> ppr con1 <+> text "and" <+> ppr con2, text "give different types for field", quotes (ppr field_name)] -dataConCtxtName :: [Located Name] -> SDoc-dataConCtxtName [con]- = text "In the definition of data constructor" <+> quotes (ppr con)-dataConCtxtName con- = text "In the definition of data constructors" <+> interpp'SP con+dataConCtxt :: [Located Name] -> SDoc+dataConCtxt cons = text "In the definition of data constructor" <> plural cons+ <+> ppr_cons cons -dataConCtxt :: Outputable a => a -> SDoc-dataConCtxt con = text "In the definition of data constructor" <+> quotes (ppr con)+dataConResCtxt :: [Located Name] -> SDoc+dataConResCtxt cons = text "In the result type of data constructor" <> plural cons+ <+> ppr_cons cons++ppr_cons :: [Located Name] -> SDoc+ppr_cons [con] = quotes (ppr con)+ppr_cons cons = interpp'SP cons classOpCtxt :: Var -> Type -> SDoc classOpCtxt sel_id tau = sep [text "When checking the class method:",
compiler/GHC/Tc/TyCl/Instance.hs view
@@ -688,9 +688,8 @@ -- Do /not/ check that the number of patterns = tyConArity fam_tc -- See [Arity of data families] in GHC.Core.FamInstEnv ; (qtvs, pats, res_kind, stupid_theta)- <- tcDataFamInstHeader mb_clsinfo fam_tc outer_bndrs- fixity hs_ctxt hs_pats m_ksig hs_cons- new_or_data+ <- tcDataFamInstHeader mb_clsinfo fam_tc outer_bndrs fixity+ hs_ctxt hs_pats m_ksig new_or_data -- Eta-reduce the axiom if possible -- Quite tricky: see Note [Implementing eta reduction for data families]@@ -740,8 +739,9 @@ do { data_cons <- tcExtendTyVarEnv qtvs $ -- For H98 decls, the tyvars scope -- over the data constructors- tcConDecls rec_rep_tc new_or_data ty_binders final_res_kind- orig_res_ty hs_cons+ tcConDecls new_or_data (DDataInstance orig_res_ty)+ rec_rep_tc ty_binders final_res_kind+ hs_cons ; rep_tc_name <- newFamInstTyConName lfam_name pats ; axiom_name <- newFamInstAxiomName lfam_name [pats]@@ -857,7 +857,7 @@ tcDataFamInstHeader :: AssocInstInfo -> TyCon -> HsOuterFamEqnTyVarBndrs GhcRn -> LexicalFixity -> LHsContext GhcRn- -> HsTyPats GhcRn -> Maybe (LHsKind GhcRn) -> [LConDecl GhcRn]+ -> HsTyPats GhcRn -> Maybe (LHsKind GhcRn) -> NewOrData -> TcM ([TyVar], [Type], Kind, ThetaType) -- The "header" of a data family instance is the part other than@@ -865,7 +865,7 @@ -- e.g. data instance D [a] :: * -> * where ... -- Here the "header" is the bit before the "where" tcDataFamInstHeader mb_clsinfo fam_tc outer_bndrs fixity- hs_ctxt hs_pats m_ksig hs_cons new_or_data+ hs_ctxt hs_pats m_ksig new_or_data = do { traceTc "tcDataFamInstHeader {" (ppr fam_tc <+> ppr hs_pats) ; (tclvl, wanted, (scoped_tvs, (stupid_theta, lhs_ty, master_res_kind, instance_res_kind))) <- pushLevelAndSolveEqualitiesX "tcDataFamInstHeader" $@@ -884,8 +884,8 @@ -- Add constraints from the result signature ; res_kind <- tc_kind_sig m_ksig - -- Add constraints from the data constructors- ; kcConDecls new_or_data res_kind hs_cons+ -- Do not add constraints from the data constructors+ -- See Note [Kind inference for data family instances] -- Check that the result kind of the TyCon applied to its args -- is compatible with the explicit signature (or Type, if there@@ -1049,6 +1049,86 @@ themselves. Heavy sigh. But not truly hard; that's what tcbVisibilities does. +Note [Kind inference for data family instances]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider this GADT-style data type declaration, where I have used+fresh variables in the data constructor's type, to stress that c,d are+quite distinct from a,b.+ data T a b where+ MkT :: forall c d. c d -> T c d++Following Note [Inferring kinds for type declarations] in GHC.Tc.TyCl,+to infer T's kind, we initially give T :: kappa, a monomorpic kind,+gather constraints from the header and data constructors, and conclude+ T :: (kappa1 -> type) -> kappa1 -> Type+Then we generalise, giving+ T :: forall k. (k->Type) -> k -> Type++Now what about a data /instance/ decl+ data family T :: forall k. (k->Type) -> k -> Type++ data instance T p Int where ...++No doubt here! The poly-kinded T is instantiated with k=Type, so the+header really looks like+ data instance T @Type (p :: Type->Type) Int where ...++But what about this?+ data instance T p q where+ MkT :: forall r. r Int -> T r Int++So what kind do 'p' and 'q' have? No clues from the header, but from+the data constructor we can clearly see that (r :: Type->Type). Does+that mean that the the /entire data instance/ is instantiated at Type,+like this?+ data instance T @Type (p :: Type->Type) (q :: Type) where+ ...++Not at all! This is a /GADT/-style decl, so the kind argument might+be specialised in this particular data constructor, thus:+ data instance T @k (p :: k->Type) (q :: k) where+ MkT :: forall (r :: Type -> Type).+ r Int -> T @Type r Int+(and perhaps specialised differently in some other data+constructor MkT2).++The key difference in this case and 'data T' at the top of this Note+is that we have no known kind for 'data T'. We thus forbid different+specialisations of T in its constructors, in an attempt to avoid+inferring polymorphic recursion. In data family T, however, there is+no problem with polymorphic recursion: we already /fully know/ T's+kind -- that came from the family declaration, and is not influenced+by the data instances -- and hence we /can/ specialise T's kind+differently in different GADT data constructors.++SHORT SUMMARY: in a data instance decl, it's not clear whether kind+constraints arising from the data constructors should be considered+local to the (GADT) data /constructor/ or should apply to the entire+data instance.++DESIGN CHOICE: in data/newtype family instance declarations, we ignore+the /data constructor/ declarations altogether, looking only at the+data instance /header/.++Observations:+* This choice is simple to describe, as well as simple to implment.+ For a data/newtype instance decl, the instance kinds are influenced+ /only/ by the header.++* We could treat Haskell-98 style data-instance decls differently, by+ taking the data constructors into account, since there are no GADT+ issues. But we don't, for simplicity, and because it means you can+ understand the data type instance by looking only at the header.++* Newtypes can be declared in GADT syntax, but they can't do GADT-style+ specialisation, so like Haskell-98 definitions we could take the+ data constructors into account. Again we don't, for the same reason.++So for now at least, we keep the simplest choice. See #18891 and !4419+for more discussion of this issue.++Kind inference for data types (Xie et al) https://arxiv.org/abs/1911.06153+takes a slightly different approach. -} @@ -2002,7 +2082,7 @@ mk_vta :: LHsExpr GhcRn -> Type -> LHsExpr GhcRn mk_vta fun ty = noLoc (HsAppType noExtField fun (mkEmptyWildCardBndrs $ nlHsParTy- $ noLoc $ XHsType $ NHsCoreTy ty))+ $ noLoc $ XHsType ty)) -- NB: use visible type application -- See Note [Default methods in instances]
compiler/GHC/Tc/TyCl/PatSyn.hs view
@@ -57,6 +57,7 @@ import GHC.Tc.TyCl.Utils import GHC.Core.ConLike import GHC.Types.FieldLabel+import GHC.Rename.Env import GHC.Data.Bag import GHC.Utils.Misc import GHC.Utils.Error@@ -95,7 +96,7 @@ ; gbl_env <- tcExtendGlobalEnv [placeholder] getGblEnv ; return (emptyBag, gbl_env) } where- (_arg_names, _rec_fields, is_infix) = collectPatSynArgInfo details+ (_arg_names, is_infix) = collectPatSynArgInfo details mk_placeholder matcher_name = mkPatSyn name is_infix ([mkTyVarBinder SpecifiedSpec alphaTyVar], []) ([], [])@@ -144,7 +145,7 @@ = addPatSynCtxt lname $ do { traceTc "tcInferPatSynDecl {" $ ppr name - ; let (arg_names, rec_fields, is_infix) = collectPatSynArgInfo details+ ; let (arg_names, is_infix) = collectPatSynArgInfo details ; (tclvl, wanted, ((lpat', args), pat_ty)) <- pushLevelAndCaptureConstraints $ tcInferPat PatSyn lpat $@@ -184,6 +185,7 @@ ; mapM_ dependentArgErr bad_args ; traceTc "tcInferPatSynDecl }" $ (ppr name $$ ppr ex_tvs)+ ; rec_fields <- lookupConstructorFields name ; tc_patsyn_finish lname dir is_infix lpat' (mkTyVarBinders InferredSpec univ_tvs , req_theta, ev_binds, req_dicts)@@ -355,7 +357,7 @@ , ppr explicit_ex_bndrs, ppr prov_theta, ppr sig_body_ty ] ; let decl_arity = length arg_names- (arg_names, rec_fields, is_infix) = collectPatSynArgInfo details+ (arg_names, is_infix) = collectPatSynArgInfo details ; (arg_tys, pat_ty) <- case tcSplitFunTysN decl_arity sig_body_ty of Right stuff -> return stuff@@ -440,6 +442,7 @@ ; traceTc "tcCheckPatSynDecl }" $ ppr name + ; rec_fields <- lookupConstructorFields name ; tc_patsyn_finish lname dir is_infix lpat' (skol_univ_bndrs, skol_req_theta, ev_binds, req_dicts) (skol_ex_bndrs, mkTyVarTys ex_tvs', skol_prov_theta, prov_dicts)@@ -623,21 +626,12 @@ -} collectPatSynArgInfo :: HsPatSynDetails GhcRn- -> ([Name], [Name], Bool)+ -> ([Name], Bool) collectPatSynArgInfo details = case details of- PrefixCon names -> (map unLoc names, [], False)- InfixCon name1 name2 -> (map unLoc [name1, name2], [], True)- RecCon names -> (vars, sels, False)- where- (vars, sels) = unzip (map splitRecordPatSyn names)- where- splitRecordPatSyn :: RecordPatSynField (Located Name)- -> (Name, Name)- splitRecordPatSyn (RecordPatSynField- { recordPatSynPatVar = L _ patVar- , recordPatSynSelectorId = L _ selId })- = (patVar, selId)+ PrefixCon _ names -> (map unLoc names, False)+ InfixCon name1 name2 -> (map unLoc [name1, name2], True)+ RecCon names -> (map (unLoc . recordPatSynPatVar) names, False) addPatSynCtxt :: Located Name -> TcM a -> TcM a addPatSynCtxt (L loc name) thing_inside@@ -663,7 +657,7 @@ -> ([TcInvisTVBinder], [TcType], [PredType], [EvTerm]) -> ([LHsExpr GhcTc], [TcType]) -- ^ Pattern arguments and types -> TcType -- ^ Pattern type- -> [Name] -- ^ Selector names+ -> [FieldLabel] -- ^ Selector names -- ^ Whether fields, empty if not record PatSyn -> TcM (LHsBinds GhcTc, TcGblEnv) tc_patsyn_finish lname dir is_infix lpat'@@ -709,13 +703,6 @@ ex_tvs prov_theta arg_tys pat_ty - -- TODO: Make this have the proper information- ; let mkFieldLabel name = FieldLabel { flLabel = occNameFS (nameOccName name)- , flIsOverloaded = False- , flSelector = name }- field_labels' = map mkFieldLabel field_labels-- -- Make the PatSyn itself ; let patSyn = mkPatSyn (unLoc lname) is_infix (univ_tvs, req_theta)@@ -723,7 +710,7 @@ arg_tys pat_ty matcher_id builder_id- field_labels'+ field_labels -- Selectors ; let rn_rec_sel_binds = mkPatSynRecSelBinds patSyn (patSynFieldLabels patSyn)@@ -935,7 +922,7 @@ (noLoc (EmptyLocalBinds noExtField)) args = case details of- PrefixCon args -> args+ PrefixCon _ args -> args InfixCon arg1 arg2 -> [arg1, arg2] RecCon args -> map recordPatSynPatVar args @@ -986,8 +973,9 @@ -> Either MsgDoc (HsExpr GhcRn) mkPrefixConExpr lcon@(L loc _) pats = do { exprs <- mapM go pats- ; return (foldl' (\x y -> HsApp noExtField (L loc x) y)- (HsVar noExtField lcon) exprs) }+ ; let con = L loc (HsVar noExtField lcon)+ ; return (unLoc $ mkHsApps con exprs)+ } mkRecordConExpr :: Located Name -> HsRecFields GhcRn (LPat GhcRn) -> Either MsgDoc (HsExpr GhcRn)@@ -1001,9 +989,9 @@ go1 :: Pat GhcRn -> Either MsgDoc (HsExpr GhcRn) go1 (ConPat NoExtField con info) = case info of- PrefixCon ps -> mkPrefixConExpr con ps- InfixCon l r -> mkPrefixConExpr con [l,r]- RecCon fields -> mkRecordConExpr con fields+ PrefixCon _ ps -> mkPrefixConExpr con ps+ InfixCon l r -> mkPrefixConExpr con [l,r]+ RecCon fields -> mkRecordConExpr con fields go1 (SigPat _ pat _) = go1 (unLoc pat) -- See Note [Type signatures and the builder expression]@@ -1186,7 +1174,7 @@ go1 _ = empty goConDetails :: HsConPatDetails GhcTc -> ([TyVar], [EvVar])- goConDetails (PrefixCon ps) = mergeMany . map go $ ps+ goConDetails (PrefixCon _ ps) = mergeMany . map go $ ps goConDetails (InfixCon p1 p2) = go p1 `merge` go p2 goConDetails (RecCon HsRecFields{ rec_flds = flds }) = mergeMany . map goRecFd $ flds
compiler/GHC/Tc/Utils/Backpack.hs view
@@ -8,6 +8,7 @@ findExtraSigImports, implicitRequirements', implicitRequirements,+ implicitRequirementsShallow, checkUnit, tcRnCheckUnit, tcRnMergeSignatures,@@ -19,7 +20,6 @@ import GHC.Prelude import GHC.Driver.Env-import GHC.Driver.Session import GHC.Driver.Ppr import GHC.Types.Basic (TypeOrKind(..))@@ -48,14 +48,14 @@ import GHC.Unit.Module.Deps import GHC.Tc.Gen.Export+import GHC.Tc.Solver import GHC.Tc.TyCl.Utils+import GHC.Tc.Types.Constraint+import GHC.Tc.Types.Origin import GHC.Tc.Utils.Monad import GHC.Tc.Utils.Instantiate import GHC.Tc.Utils.TcMType import GHC.Tc.Utils.TcType-import GHC.Tc.Solver-import GHC.Tc.Types.Constraint-import GHC.Tc.Types.Origin import GHC.Hs @@ -86,7 +86,6 @@ import Control.Monad import Data.List (find)-import qualified Data.Map as Map import {-# SOURCE #-} GHC.Tc.Module @@ -175,7 +174,8 @@ -- The hsig did NOT define this function; that means it must -- be a reexport. In this case, make sure the 'Name' of the -- reexport matches the 'Name exported here.- | [GRE { gre_name = name' }] <- lookupGlobalRdrEnv gr (nameOccName name) =+ | [gre] <- lookupGlobalRdrEnv gr (nameOccName name) = do+ let name' = greMangledName gre when (name /= name') $ do -- See Note [Error reporting bad reexport] -- TODO: Actually this error swizzle doesn't work@@ -247,19 +247,6 @@ (implic, _) <- buildImplicationFor tclvl skol_info tvs_skols [] unsolved reportAllUnsolved (mkImplicWC implic) --- | Return this list of requirement interfaces that need to be merged--- to form @mod_name@, or @[]@ if this is not a requirement.-requirementMerges :: UnitState -> ModuleName -> [InstantiatedModule]-requirementMerges unit_state mod_name =- fmap fixupModule $ fromMaybe [] (Map.lookup mod_name (requirementContext unit_state))- where- -- update IndefUnitId ppr info as they may have changed since the- -- time the IndefUnitId was created- fixupModule (Module iud name) = Module iud' name- where- iud' = iud { instUnitInstanceOf = cid }- cid = instUnitInstanceOf iud- -- | For a module @modname@ of type 'HscSource', determine the list -- of extra "imports" of other requirements which should be considered part of -- the import of the requirement, because it transitively depends on those@@ -267,12 +254,12 @@ -- is something like this: -- -- unit p where--- signature A--- signature B--- import A+-- signature X+-- signature Y+-- import X -- -- unit q where--- dependency p[A=\<A>,B=\<B>]+-- dependency p[X=\<A>,Y=\<B>] -- signature A -- signature B --@@ -291,7 +278,7 @@ $ moduleFreeHolesPrecise (text "findExtraSigImports") (mkModule (VirtUnit iuid) mod_name))) where- unit_state = unitState (hsc_dflags hsc_env)+ unit_state = hsc_units hsc_env reqs = requirementMerges unit_state modname findExtraSigImports' _ _ _ = return emptyUniqDSet@@ -306,7 +293,7 @@ | mod_name <- uniqDSetToList extra_requirements ] -- A version of 'implicitRequirements'' which is more friendly--- for "GHC.Driver.Make" and "GHC.Tc.Module".+-- for "GHC.Tc.Module". implicitRequirements :: HscEnv -> [(Maybe FastString, Located ModuleName)] -> IO [(Maybe FastString, Located ModuleName)]@@ -316,7 +303,7 @@ -- Given a list of 'import M' statements in a module, figure out -- any extra implicit requirement imports they may have. For--- example, if they 'import M' and M resolves to p[A=<B>], then+-- example, if they 'import M' and M resolves to p[A=<B>,C=D], then -- they actually also import the local requirement B. implicitRequirements' :: HscEnv -> [(Maybe FastString, Located ModuleName)]@@ -331,6 +318,28 @@ _ -> return [] where home_unit = hsc_home_unit hsc_env +-- | Like @implicitRequirements'@, but returns either the module name, if it is+-- a free hole, or the instantiated unit the imported module is from, so that+-- that instantiated unit can be processed and via the batch mod graph (rather+-- than a transitive closure done here) all the free holes are still reachable.+implicitRequirementsShallow+ :: HscEnv+ -> [(Maybe FastString, Located ModuleName)]+ -> IO ([ModuleName], [InstantiatedUnit])+implicitRequirementsShallow hsc_env normal_imports = go ([], []) normal_imports+ where+ go acc [] = pure acc+ go (accL, accR) ((mb_pkg, L _ imp):imports) = do+ found <- findImportedModule hsc_env imp mb_pkg+ let acc' = case found of+ Found _ mod | not (isHomeModule (hsc_home_unit hsc_env) mod) ->+ case moduleUnit mod of+ HoleUnit -> (moduleName mod : accL, accR)+ RealUnit _ -> (accL, accR)+ VirtUnit u -> (accL, u:accR)+ _ -> (accL, accR)+ go acc' imports+ -- | Given a 'Unit', make sure it is well typed. This is because -- unit IDs come from Cabal, which does not know if things are well-typed or -- not; a component may have been filled with implementations for the holes@@ -360,7 +369,7 @@ initTc hsc_env HsigFile -- bogus False- (mainModIs dflags)+ (mainModIs hsc_env) (realSrcLocSpan (mkRealSrcLoc (fsLit loc_str) 0 0)) -- bogus $ checkUnit uid where@@ -522,7 +531,6 @@ -- file, which is guaranteed to exist, see -- Note [Blank hsigs for all requirements] hsc_env <- getTopEnv- dflags <- getDynFlags -- Copy over some things from the original TcGblEnv that -- we want to preserve@@ -552,7 +560,7 @@ let outer_mod = tcg_mod tcg_env inner_mod = tcg_semantic_mod tcg_env mod_name = moduleName (tcg_mod tcg_env)- unit_state = unitState dflags+ unit_state = hsc_units hsc_env home_unit = hsc_home_unit hsc_env -- STEP 1: Figure out all of the external signature interfaces@@ -753,7 +761,7 @@ let ifaces = lcl_iface : ext_ifaces -- STEP 4.1: Merge fixities (we'll verify shortly) tcg_fix_env- let fix_env = mkNameEnv [ (gre_name rdr_elt, FixItem occ f)+ let fix_env = mkNameEnv [ (greMangledName rdr_elt, FixItem occ f) | (occ, f) <- concatMap mi_fixities ifaces , rdr_elt <- lookupGlobalRdrEnv rdr_env occ ] @@ -928,9 +936,8 @@ -- explicitly.) checkImplements :: Module -> InstantiatedModule -> TcRn TcGblEnv checkImplements impl_mod req_mod@(Module uid mod_name) = do- dflags <- getDynFlags hsc_env <- getTopEnv- let unit_state = unitState dflags+ let unit_state = hsc_units hsc_env home_unit = hsc_home_unit hsc_env addErrCtxt (impl_msg unit_state impl_mod req_mod) $ do let insts = instUnitInsts uid@@ -954,7 +961,7 @@ let avails = calculateAvails home_unit impl_iface False{- safe -} NotBoot ImportedBySystem- fix_env = mkNameEnv [ (gre_name rdr_elt, FixItem occ f)+ fix_env = mkNameEnv [ (greMangledName rdr_elt, FixItem occ f) | (occ, f) <- mi_fixities impl_iface , rdr_elt <- lookupGlobalRdrEnv impl_gr occ ] updGblEnv (\tcg_env -> tcg_env {
compiler/GHC/Tc/Utils/Env.hs view
@@ -102,6 +102,7 @@ import GHC.Core.TyCon import GHC.Core.Type import GHC.Core.Coercion.Axiom+import GHC.Core.Coercion import GHC.Core.Class import GHC.Unit.Module@@ -663,9 +664,43 @@ ; wrapper <- case actual_u of Bottom -> return idHsWrapper Zero -> tcSubMult (UsageEnvironmentOf name) Many id_mult- MUsage m -> tcSubMult (UsageEnvironmentOf name) m id_mult+ MUsage m -> do { m <- zonkTcType m+ ; m <- promote_mult m+ ; tcSubMult (UsageEnvironmentOf name) m id_mult } ; tcEmitBindingUsage (deleteUE uenv name) ; return wrapper }++ -- This is gross. The problem is in test case typecheck/should_compile/T18998:+ -- f :: a %1-> Id n a -> Id n a+ -- f x (MkId _) = MkId x+ -- where MkId is a GADT constructor. Multiplicity polymorphism of constructors+ -- invents a new multiplicity variable p[2] for the application MkId x. This+ -- variable is at level 2, bumped because of the GADT pattern-match (MkId _).+ -- We eventually unify the variable with One, due to the call to tcSubMult in+ -- tcCheckUsage. But by then, we're at TcLevel 1, and so the level-check+ -- fails.+ --+ -- What to do? If we did inference "for real", the sub-multiplicity constraint+ -- would end up in the implication of the GADT pattern-match, and all would+ -- be well. But we don't have a real sub-multiplicity constraint to put in+ -- the implication. (Multiplicity inference works outside the usual generate-+ -- constraints-and-solve scheme.) Here, where the multiplicity arrives, we+ -- must promote all multiplicity variables to reflect this outer TcLevel.+ -- It's reminiscent of floating a constraint, really, so promotion is+ -- appropriate. The promoteTcType function works only on types of kind TYPE rr,+ -- so we can't use it here. Thus, this dirtiness.+ --+ -- It works nicely in practice.+ (promote_mult, _, _, _) = mapTyCo mapper+ mapper = TyCoMapper { tcm_tyvar = \ () tv -> if isMetaTyVar tv+ then do { tclvl <- getTcLevel+ ; _ <- promoteMetaTyVarTo tclvl tv+ ; zonkTcTyVar tv }+ else return (mkTyVarTy tv)+ , tcm_covar = \ () cv -> return (mkCoVarCo cv)+ , tcm_hole = \ () h -> return (mkHoleCo h)+ , tcm_tycobinder = \ () tcv _flag -> return ((), tcv)+ , tcm_tycon = return } {- ********************************************************************* * *
compiler/GHC/Tc/Utils/Instantiate.hs view
@@ -42,6 +42,7 @@ import GHC.Prelude import GHC.Driver.Session+import GHC.Driver.Env import GHC.Builtin.Types ( heqDataCon, eqDataCon, integerTyConName ) import GHC.Builtin.Names@@ -975,7 +976,7 @@ addClsInstsErr :: SDoc -> [ClsInst] -> TcRn () addClsInstsErr herald ispecs = do- unit_state <- unitState <$> getDynFlags+ unit_state <- hsc_units <$> getTopEnv setSrcSpan (getSrcSpan (head sorted)) $ addErr $ pprWithUnitState unit_state $ (hang herald 2 (pprInstances sorted)) where
compiler/GHC/Tc/Utils/Monad.hs view
@@ -111,7 +111,7 @@ getTcLevel, setTcLevel, isTouchableTcM, getLclTypeEnv, setLclTypeEnv, traceTcConstraints,- emitNamedTypeHole, emitAnonTypeHole,+ emitNamedTypeHole, IsExtraConstraint(..), emitAnonTypeHole, -- * Template Haskell context recordThUse, recordThSpliceUse,@@ -773,7 +773,7 @@ dumpTcRn :: Bool -> DumpOptions -> String -> DumpFormat -> SDoc -> TcRn () dumpTcRn useUserStyle dumpOpt title fmt doc = do dflags <- getDynFlags- printer <- getPrintUnqualified dflags+ printer <- getPrintUnqualified real_doc <- wrapDocLoc doc let sty = if useUserStyle then mkUserStyle printer AllTheWay@@ -792,19 +792,17 @@ else return doc -getPrintUnqualified :: DynFlags -> TcRn PrintUnqualified-getPrintUnqualified dflags+getPrintUnqualified :: TcRn PrintUnqualified+getPrintUnqualified = do { rdr_env <- getGlobalRdrEnv ; hsc_env <- getTopEnv- ; let unit_state = unitState dflags- ; let home_unit = hsc_home_unit hsc_env- ; return $ mkPrintUnqualified unit_state home_unit rdr_env }+ ; return $ mkPrintUnqualified (hsc_unit_env hsc_env) rdr_env } -- | Like logInfoTcRn, but for user consumption printForUserTcRn :: SDoc -> TcRn () printForUserTcRn doc = do { dflags <- getDynFlags- ; printer <- getPrintUnqualified dflags+ ; printer <- getPrintUnqualified ; liftIO (printOutputForUser dflags printer doc) } {-@@ -998,16 +996,16 @@ mkLongErrAt :: SrcSpan -> MsgDoc -> MsgDoc -> TcRn ErrMsg mkLongErrAt loc msg extra = do { dflags <- getDynFlags ;- printer <- getPrintUnqualified dflags ;- unit_state <- unitState <$> getDynFlags ;+ printer <- getPrintUnqualified ;+ unit_state <- hsc_units <$> getTopEnv ; let msg' = pprWithUnitState unit_state msg in return $ mkLongErrMsg dflags loc printer msg' extra } mkErrDocAt :: SrcSpan -> ErrDoc -> TcRn ErrMsg mkErrDocAt loc errDoc = do { dflags <- getDynFlags ;- printer <- getPrintUnqualified dflags ;- unit_state <- unitState <$> getDynFlags ;+ printer <- getPrintUnqualified ;+ unit_state <- hsc_units <$> getTopEnv ; let f = pprWithUnitState unit_state errDoc' = mapErrDoc f errDoc in@@ -1519,7 +1517,7 @@ add_warn_at :: WarnReason -> SrcSpan -> MsgDoc -> MsgDoc -> TcRn () add_warn_at reason loc msg extra_info = do { dflags <- getDynFlags ;- printer <- getPrintUnqualified dflags ;+ printer <- getPrintUnqualified ; let { warn = mkLongWarnMsg dflags loc printer msg extra_info } ; reportWarning reason warn }@@ -1779,16 +1777,26 @@ hang (text (msg ++ ": LIE:")) 2 (ppr lie) } -emitAnonTypeHole :: TcTyVar -> TcM ()-emitAnonTypeHole tv+data IsExtraConstraint = YesExtraConstraint+ | NoExtraConstraint++instance Outputable IsExtraConstraint where+ ppr YesExtraConstraint = text "YesExtraConstraint"+ ppr NoExtraConstraint = text "NoExtraConstraint"++emitAnonTypeHole :: IsExtraConstraint+ -> TcTyVar -> TcM ()+emitAnonTypeHole extra_constraints tv = do { ct_loc <- getCtLocM (TypeHoleOrigin occ) Nothing- ; let hole = Hole { hole_sort = TypeHole+ ; let hole = Hole { hole_sort = sort , hole_occ = occ , hole_ty = mkTyVarTy tv , hole_loc = ct_loc } ; emitHole hole } where occ = mkTyVarOcc "_"+ sort | YesExtraConstraint <- extra_constraints = ConstraintHole+ | otherwise = TypeHole emitNamedTypeHole :: (Name, TcTyVar) -> TcM () emitNamedTypeHole (name, tv)@@ -1857,7 +1865,7 @@ class constraints mentioned above. But we may /also/ end up taking constraints built at some inner level, and emitting them at some outer level, and then breaking the TcLevel invariants- See Note [TcLevel and untouchable type variables] in GHC.Tc.Utils.TcType+ See Note [TcLevel invariants] in GHC.Tc.Utils.TcType So dropMisleading has a horridly ad-hoc structure. It keeps only /insoluble/ flat constraints (which are unlikely to very visibly trip
compiler/GHC/Tc/Utils/TcMType.hs view
@@ -25,7 +25,7 @@ newOpenFlexiTyVar, newOpenFlexiTyVarTy, newOpenTypeKind, newMetaKindVar, newMetaKindVars, newMetaTyVarTyAtLevel, newAnonMetaTyVar, cloneMetaTyVar,- newFmvTyVar, newFskTyVar,+ newCycleBreakerTyVar, newMultiplicityVar, readMetaTyVar, writeMetaTyVar, writeMetaTyVarRef,@@ -80,7 +80,7 @@ --------------------------------- -- Promotion, defaulting, skolemisation- defaultTyVar, promoteTyVar, promoteTyVarSet,+ defaultTyVar, promoteMetaTyVarTo, promoteTyVarSet, quantifyTyVars, isQuantifiableTv, skolemiseUnboundMetaTyVar, zonkAndSkolemise, skolemiseQuantifiedTyVar, @@ -120,7 +120,6 @@ import GHC.Types.Name import GHC.Types.Var.Set import GHC.Builtin.Types-import GHC.Builtin.Types.Prim import GHC.Types.Var.Env import GHC.Types.Name.Env import GHC.Utils.Misc@@ -183,7 +182,7 @@ -- Deals with both equality and non-equality predicates newWanted orig t_or_k pty = do loc <- getCtLocM orig t_or_k- d <- if isEqPrimPred pty then HoleDest <$> newCoercionHole YesBlockSubst pty+ d <- if isEqPrimPred pty then HoleDest <$> newCoercionHole pty else EvVarDest <$> newEvVar pty return $ CtWanted { ctev_dest = d , ctev_pred = pty@@ -199,8 +198,8 @@ cloneWanted :: Ct -> TcM Ct cloneWanted ct- | ev@(CtWanted { ctev_dest = HoleDest old_hole, ctev_pred = pty }) <- ctEvidence ct- = do { co_hole <- newCoercionHole (ch_blocker old_hole) pty+ | ev@(CtWanted { ctev_pred = pty }) <- ctEvidence ct+ = do { co_hole <- newCoercionHole pty ; return (mkNonCanonical (ev { ctev_dest = HoleDest co_hole })) } | otherwise = return ct@@ -250,7 +249,7 @@ -- | Emits a new equality constraint emitWantedEq :: CtOrigin -> TypeOrKind -> Role -> TcType -> TcType -> TcM Coercion emitWantedEq origin t_or_k role ty1 ty2- = do { hole <- newCoercionHole YesBlockSubst pty+ = do { hole <- newCoercionHole pty ; loc <- getCtLocM origin (Just t_or_k) ; emitSimple $ mkNonCanonical $ CtWanted { ctev_pred = pty, ctev_dest = HoleDest hole@@ -276,16 +275,21 @@ emitWantedEvVars orig = mapM (emitWantedEvVar orig) -- | Emit a new wanted expression hole-emitNewExprHole :: OccName -- of the hole- -> Id -- of the evidence- -> Type -> TcM ()-emitNewExprHole occ ev_id ty- = do { loc <- getCtLocM (ExprHoleOrigin occ) (Just TypeLevel)- ; let hole = Hole { hole_sort = ExprHole ev_id- , hole_occ = getOccName ev_id+emitNewExprHole :: OccName -- of the hole+ -> Type -> TcM HoleExprRef+emitNewExprHole occ ty+ = do { u <- newUnique+ ; ref <- newTcRef (pprPanic "unfilled unbound-variable evidence" (ppr u))+ ; let her = HER ref ty u++ ; loc <- getCtLocM (ExprHoleOrigin occ) (Just TypeLevel)++ ; let hole = Hole { hole_sort = ExprHole her+ , hole_occ = occ , hole_ty = ty , hole_loc = loc }- ; emitHole hole }+ ; emitHole hole+ ; return her } newDict :: Class -> [TcType] -> TcM DictId newDict cls tys@@ -323,16 +327,12 @@ ************************************************************************ -} -newCoercionHole :: BlockSubstFlag -- should the presence of this hole block substitution?- -- See sub-wrinkle in TcCanonical- -- Note [Equalities with incompatible kinds]- -> TcPredType -> TcM CoercionHole-newCoercionHole blocker pred_ty+newCoercionHole :: TcPredType -> TcM CoercionHole+newCoercionHole pred_ty = do { co_var <- newEvVar pred_ty- ; traceTc "New coercion hole:" (ppr co_var <+> ppr blocker)+ ; traceTc "New coercion hole:" (ppr co_var) ; ref <- newMutVar Nothing- ; return $ CoercionHole { ch_co_var = co_var, ch_blocker = blocker- , ch_ref = ref } }+ ; return $ CoercionHole { ch_co_var = co_var, ch_ref = ref } } -- | Put a value in a coercion hole fillCoercionHole :: CoercionHole -> Coercion -> TcM ()@@ -805,11 +805,10 @@ metaInfoToTyVarName :: MetaInfo -> FastString metaInfoToTyVarName meta_info = case meta_info of- TauTv -> fsLit "t"- FlatMetaTv -> fsLit "fmv"- FlatSkolTv -> fsLit "fsk"- TyVarTv -> fsLit "a"- RuntimeUnkTv -> fsLit "r"+ TauTv -> fsLit "t"+ TyVarTv -> fsLit "a"+ RuntimeUnkTv -> fsLit "r"+ CycleBreakerTv -> fsLit "b" newAnonMetaTyVar :: MetaInfo -> Kind -> TcM TcTyVar newAnonMetaTyVar mi = newNamedAnonMetaTyVar (metaInfoToTyVarName mi) mi@@ -875,19 +874,13 @@ ; traceTc "cloneAnonMetaTyVar" (ppr tyvar <+> dcolon <+> ppr (tyVarKind tyvar)) ; return tyvar } -newFskTyVar :: TcType -> TcM TcTyVar-newFskTyVar fam_ty- = do { details <- newMetaDetails FlatSkolTv- ; name <- newMetaTyVarName (fsLit "fsk")- ; return (mkTcTyVar name (tcTypeKind fam_ty) details) }--newFmvTyVar :: TcType -> TcM TcTyVar--- Very like newMetaTyVar, except sets mtv_tclvl to one less--- so that the fmv is untouchable.-newFmvTyVar fam_ty- = do { details <- newMetaDetails FlatMetaTv- ; name <- newMetaTyVarName (fsLit "s")- ; return (mkTcTyVar name (tcTypeKind fam_ty) details) }+-- Make a new CycleBreakerTv. See Note [Type variable cycles in Givens]+-- in GHC.Tc.Solver.Canonical.+newCycleBreakerTyVar :: TcKind -> TcM TcTyVar+newCycleBreakerTyVar kind+ = do { details <- newMetaDetails CycleBreakerTv+ ; name <- newMetaTyVarName (fsLit "cbv")+ ; return (mkTcTyVar name kind details) } newMetaDetails :: MetaInfo -> TcM TcTyVarDetails newMetaDetails info@@ -976,12 +969,18 @@ ; writeTcRef ref (Indirect ty) } -- Everything from here on only happens if DEBUG is on+ -- Need to zonk 'ty' because we may only recently have promoted+ -- its free meta-tyvars (see Solver.Interact.tryToSolveByUnification) | otherwise = do { meta_details <- readMutVar ref; -- Zonk kinds to allow the error check to work ; zonked_tv_kind <- zonkTcType tv_kind- ; zonked_ty_kind <- zonkTcType ty_kind- ; let kind_check_ok = tcIsConstraintKind zonked_tv_kind+ ; zonked_ty <- zonkTcType ty+ ; let zonked_ty_kind = tcTypeKind zonked_ty+ zonked_ty_lvl = tcTypeLevel zonked_ty+ level_check_ok = not (zonked_ty_lvl `strictlyDeeperThan` tv_lvl)+ level_check_msg = ppr zonked_ty_lvl $$ ppr tv_lvl $$ ppr tyvar $$ ppr ty+ kind_check_ok = tcIsConstraintKind zonked_tv_kind || tcEqKind zonked_ty_kind zonked_tv_kind -- Hack alert! tcIsConstraintKind: see GHC.Tc.Gen.HsType -- Note [Extra-constraint holes in partial type signatures]@@ -997,7 +996,6 @@ ; MASSERT2( isFlexi meta_details, double_upd_msg meta_details ) -- Check for level OK- -- See Note [Level check when unifying] ; MASSERT2( level_check_ok, level_check_msg ) -- Check Kinds ok@@ -1007,34 +1005,14 @@ ; writeMutVar ref (Indirect ty) } where tv_kind = tyVarKind tyvar- ty_kind = tcTypeKind ty tv_lvl = tcTyVarLevel tyvar- ty_lvl = tcTypeLevel ty - level_check_ok = not (ty_lvl `strictlyDeeperThan` tv_lvl)- level_check_msg = ppr ty_lvl $$ ppr tv_lvl $$ ppr tyvar $$ ppr ty double_upd_msg details = hang (text "Double update of meta tyvar") 2 (ppr tyvar $$ ppr details) -{- Note [Level check when unifying]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When unifying- alpha:lvl := ty-we expect that the TcLevel of 'ty' will be <= lvl.-However, during unflatting we do- fuv:l := ty:(l+1)-which is usually wrong; hence the check isFmmvTyVar in level_check_ok.-See Note [TcLevel assignment] in GHC.Tc.Utils.TcType.--}- {--% Generating fresh variables for pattern match check--}---{- ************************************************************************ * * MetaTvs: TauTvs@@ -1258,6 +1236,9 @@ generalisation, because at that moment we have a clear picture of what skolems are in scope within the type itself (e.g. that 'forall arg'). +This change is inspired by and described in Section 7.2 of "Kind Inference+for Datatypes", POPL'20.+ Wrinkle: We must make absolutely sure that alpha indeed is not@@ -1598,8 +1579,8 @@ Note [Use level numbers for quantification] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The level numbers assigned to metavariables are very useful. Not only-do they track touchability (Note [TcLevel and untouchable type variables]-in GHC.Tc.Utils.TcType), but they also allow us to determine which variables to+do they track touchability (Note [TcLevel invariants] in GHC.Tc.Utils.TcType),+but they also allow us to determine which variables to generalise. The rule is this: When generalising, quantify only metavariables with a TcLevel greater@@ -2033,29 +2014,31 @@ * * ********************************************************************* -} -promoteTyVar :: TcTyVar -> TcM Bool+promoteMetaTyVarTo :: TcLevel -> TcTyVar -> TcM Bool -- When we float a constraint out of an implication we must restore--- invariant (WantedInv) in Note [TcLevel and untouchable type variables] in GHC.Tc.Utils.TcType+-- invariant (WantedInv) in Note [TcLevel invariants] in GHC.Tc.Utils.TcType -- Return True <=> we did some promotion -- Also returns either the original tyvar (no promotion) or the new one -- See Note [Promoting unification variables]-promoteTyVar tv- = do { tclvl <- getTcLevel- ; if (isFloatedTouchableMetaTyVar tclvl tv)- then do { cloned_tv <- cloneMetaTyVar tv- ; let rhs_tv = setMetaTyVarTcLevel cloned_tv tclvl- ; writeMetaTyVar tv (mkTyVarTy rhs_tv)- ; traceTc "promoteTyVar" (ppr tv <+> text "-->" <+> ppr rhs_tv)- ; return True }- else do { traceTc "promoteTyVar: no" (ppr tv)- ; return False } }+promoteMetaTyVarTo tclvl tv+ | ASSERT2( isMetaTyVar tv, ppr tv )+ tcTyVarLevel tv `strictlyDeeperThan` tclvl+ = do { cloned_tv <- cloneMetaTyVar tv+ ; let rhs_tv = setMetaTyVarTcLevel cloned_tv tclvl+ ; writeMetaTyVar tv (mkTyVarTy rhs_tv)+ ; traceTc "promoteTyVar" (ppr tv <+> text "-->" <+> ppr rhs_tv)+ ; return True }+ | otherwise+ = return False -- Returns whether or not *any* tyvar is defaulted promoteTyVarSet :: TcTyVarSet -> TcM Bool promoteTyVarSet tvs- = do { bools <- mapM promoteTyVar (nonDetEltsUniqSet tvs)+ = do { tclvl <- getTcLevel+ ; bools <- mapM (promoteMetaTyVarTo tclvl) $+ filter isPromotableMetaTyVar $+ nonDetEltsUniqSet tvs -- Non-determinism is OK because order of promotion doesn't matter- ; return (or bools) } @@ -2161,8 +2144,6 @@ zonkHole hole@(Hole { hole_ty = ty }) = do { ty' <- zonkTcType ty ; return (hole { hole_ty = ty' }) }- -- No need to zonk the Id in any ExprHole because we never look at it- -- until after the final zonk and desugaring {- Note [zonkCt behaviour] ~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -2179,18 +2160,16 @@ - For CIrredCan we want to see if a constraint is insoluble with insolubleWC -On the other hand, we change CTyEqCan to CNonCanonical, because of all of-CTyEqCan's invariants, which can break during zonking. Besides, the constraint+On the other hand, we change CEqCan to CNonCanonical, because of all of+CEqCan's invariants, which can break during zonking. (Example: a ~R alpha, where+we have alpha := N Int, where N is a newtype.) Besides, the constraint will be canonicalised again, so there is little benefit in keeping the-CTyEqCan structure.--NB: we do not expect to see any CFunEqCans, because zonkCt is only-called on unflattened constraints.+CEqCan structure. -NB: Constraints are always re-flattened etc by the canonicaliser in+NB: Constraints are always rewritten etc by the canonicaliser in @GHC.Tc.Solver.Canonical@ even if they come in as CDictCan. Only canonical constraints that are actually in the inert set carry all the guarantees. So it is okay if zonkCt-creates e.g. a CDictCan where the cc_tyars are /not/ function free.+creates e.g. a CDictCan where the cc_tyars are /not/ fully reduced. -} zonkCt :: Ct -> TcM Ct@@ -2200,7 +2179,7 @@ ; args' <- mapM zonkTcType args ; return $ ct { cc_ev = ev', cc_tyargs = args' } } -zonkCt (CTyEqCan { cc_ev = ev })+zonkCt (CEqCan { cc_ev = ev }) = mkNonCanonical <$> zonkCtEvidence ev zonkCt ct@(CIrredCan { cc_ev = ev }) -- Preserve the cc_status flag@@ -2208,10 +2187,7 @@ ; return (ct { cc_ev = ev' }) } zonkCt ct- = ASSERT( not (isCFunEqCan ct) )- -- We do not expect to see any CFunEqCans, because zonkCt is only called on- -- unflattened constraints.- do { fl' <- zonkCtEvidence (ctEvidence ct)+ = do { fl' <- zonkCtEvidence (ctEvidence ct) ; return (mkNonCanonical fl') } zonkCtEvidence :: CtEvidence -> TcM CtEvidence
compiler/GHC/Tc/Utils/Unify.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} @@ -36,7 +37,8 @@ matchExpectedFunKind, matchActualFunTySigma, matchActualFunTysRho, - metaTyVarUpdateOK, occCheckForErrors, MetaTyVarUpdateResult(..)+ occCheckForErrors, CheckTyEqResult(..),+ checkTyVarEq, checkTyFamEq, checkTypeEq, AreTypeFamiliesOK(..) ) where @@ -73,8 +75,10 @@ import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic +import GHC.Exts ( inline ) import Control.Monad import Control.Arrow ( second )+import qualified Data.Semigroup as S {- *********************************************************************@@ -150,9 +154,10 @@ defer fun_ty = do { arg_ty <- newOpenFlexiTyVarTy ; res_ty <- newOpenFlexiTyVarTy- ; let unif_fun_ty = mkVisFunTyMany arg_ty res_ty+ ; mult <- newFlexiTyVarTy multiplicityTy+ ; let unif_fun_ty = mkVisFunTy mult arg_ty res_ty ; co <- unifyType mb_thing fun_ty unif_fun_ty- ; return (mkWpCastN co, unrestricted arg_ty, res_ty) }+ ; return (mkWpCastN co, Scaled mult arg_ty, res_ty) } ------------ mk_ctxt :: TcType -> TidyEnv -> TcM (TidyEnv, MsgDoc)@@ -356,12 +361,12 @@ ------------ defer :: [Scaled ExpSigmaType] -> Arity -> ExpRhoType -> TcM (HsWrapper, a) defer acc_arg_tys n fun_ty- = do { more_arg_tys <- replicateM n newInferExpType+ = do { more_arg_tys <- replicateM n (mkScaled <$> newFlexiTyVarTy multiplicityTy <*> newInferExpType) ; res_ty <- newInferExpType- ; result <- thing_inside (reverse acc_arg_tys ++ (map unrestricted more_arg_tys)) res_ty- ; more_arg_tys <- mapM readExpType more_arg_tys+ ; 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 ; res_ty <- readExpType res_ty- ; let unif_fun_ty = mkVisFunTysMany more_arg_tys res_ty+ ; let unif_fun_ty = mkVisFunTys more_arg_tys res_ty ; wrap <- tcSubType AppOrigin ctx unif_fun_ty fun_ty -- Not a good origin at all :-( ; return (wrap, result) }@@ -949,7 +954,7 @@ ; return (implic { ic_tclvl = tclvl , ic_skols = skol_tvs- , ic_no_eqs = True+ , ic_given_eqs = NoGivenEqs , ic_wanted = wanted , ic_binds = ev_binds , ic_info = skol_info }) }@@ -1166,17 +1171,17 @@ -- so that type variables tend to get filled in with -- the most informative version of the type go (TyVarTy tv1) ty2- = do { lookup_res <- lookupTcTyVar tv1+ = do { lookup_res <- isFilledMetaTyVar_maybe tv1 ; case lookup_res of- Filled ty1 -> do { traceTc "found filled tyvar" (ppr tv1 <+> text ":->" <+> ppr ty1)- ; go ty1 ty2 }- Unfilled _ -> uUnfilledVar origin t_or_k NotSwapped tv1 ty2 }+ Just ty1 -> do { traceTc "found filled tyvar" (ppr tv1 <+> text ":->" <+> ppr ty1)+ ; go ty1 ty2 }+ Nothing -> uUnfilledVar origin t_or_k NotSwapped tv1 ty2 } go ty1 (TyVarTy tv2)- = do { lookup_res <- lookupTcTyVar tv2+ = do { lookup_res <- isFilledMetaTyVar_maybe tv2 ; case lookup_res of- Filled ty2 -> do { traceTc "found filled tyvar" (ppr tv2 <+> text ":->" <+> ppr ty2)- ; go ty1 ty2 }- Unfilled _ -> uUnfilledVar origin t_or_k IsSwapped tv2 ty1 }+ Just ty2 -> do { traceTc "found filled tyvar" (ppr tv2 <+> text ":->" <+> ppr ty2)+ ; go ty1 ty2 }+ Nothing -> uUnfilledVar origin t_or_k IsSwapped tv2 ty1 } -- See Note [Expanding synonyms during unification] go ty1@(TyConApp tc1 []) (TyConApp tc2 [])@@ -1430,9 +1435,12 @@ ; go dflags cur_lvl } where go dflags cur_lvl- | canSolveByUnification cur_lvl tv1 ty2- , MTVU_OK ty2' <- metaTyVarUpdateOK dflags tv1 ty2- = do { co_k <- uType KindLevel kind_origin (tcTypeKind ty2') (tyVarKind tv1)+ | isTouchableMetaTyVar cur_lvl tv1+ -- See Note [Unification preconditions], (UNTOUCHABLE) wrinkles+ , canSolveByUnification (metaTyVarInfo tv1) ty2+ , CTE_OK <- checkTyVarEq dflags NoTypeFamilies tv1 ty2+ -- See Note [Prevent unification with type families] about the NoTypeFamilies:+ = do { co_k <- uType KindLevel kind_origin (tcTypeKind ty2) (tyVarKind tv1) ; traceTc "uUnfilledVar2 ok" $ vcat [ ppr tv1 <+> dcolon <+> ppr (tyVarKind tv1) , ppr ty2 <+> dcolon <+> ppr (tcTypeKind ty2)@@ -1442,8 +1450,8 @@ -- Only proceed if the kinds match -- NB: tv1 should still be unfilled, despite the kind unification -- because tv1 is not free in ty2 (or, hence, in its kind)- then do { writeMetaTyVar tv1 ty2'- ; return (mkTcNomReflCo ty2') }+ then do { writeMetaTyVar tv1 ty2+ ; return (mkTcNomReflCo ty2) } else defer } -- This cannot be solved now. See GHC.Tc.Solver.Canonical -- Note [Equalities with incompatible kinds]@@ -1460,6 +1468,22 @@ defer = unSwap swapped (uType_defer t_or_k origin) ty1 ty2 +canSolveByUnification :: MetaInfo -> TcType -> Bool+-- See Note [Unification preconditions, (TYVAR-TV)]+canSolveByUnification info xi+ = case info of+ CycleBreakerTv -> False+ TyVarTv -> case tcGetTyVar_maybe xi of+ Nothing -> False+ Just tv -> case tcTyVarDetails tv of+ MetaTv { mtv_info = info }+ -> case info of+ TyVarTv -> True+ _ -> False+ SkolemTv {} -> True+ RuntimeUnk -> True+ _ -> True+ swapOverTyVars :: Bool -> TcTyVar -> TcTyVar -> Bool swapOverTyVars is_given tv1 tv2 -- See Note [Unification variables on the left]@@ -1498,20 +1522,105 @@ RuntimeUnk -> 0 SkolemTv {} -> 0 MetaTv { mtv_info = info } -> case info of- FlatSkolTv -> 1- TyVarTv -> 2- TauTv -> 3- FlatMetaTv -> 4- RuntimeUnkTv -> 5+ CycleBreakerTv -> 0+ TyVarTv -> 1+ TauTv -> 2+ RuntimeUnkTv -> 3 -{- Note [TyVar/TyVar orientation]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Given (a ~ b), should we orient the CTyEqCan as (a~b) or (b~a)?+{- Note [Unification preconditions]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Question: given a homogeneous equality (alpha ~# ty), when is it OK to+unify alpha := ty?++This note only applied to /homogeneous/ equalities, in which both+sides have the same kind.++There are three reasons not to unify:++1. (SKOL-ESC) Skolem-escape+ Consider the constraint+ forall[2] a[2]. alpha[1] ~ Maybe a[2]+ If we unify alpha := Maybe a, the skolem 'a' may escape its scope.+ The level alpha[1] says that alpha may be used outside this constraint,+ where 'a' is not in scope at all. So we must not unify.++ Bottom line: when looking at a constraint alpha[n] := ty, do not unify+ if any free variable of 'ty' has level deeper (greater) than n++2. (UNTOUCHABLE) Untouchable unification variables+ Consider the constraint+ forall[2] a[2]. b[1] ~ Int => alpha[1] ~ Int+ There is no (SKOL-ESC) problem with unifying alpha := Int, but it might+ not be the principal solution. Perhaps the "right" solution is alpha := b.+ We simply can't tell. See "OutsideIn(X): modular type inference with local+ assumptions", section 2.2. We say that alpha[1] is "untouchable" inside+ this implication.++ Bottom line: at amibient level 'l', when looking at a constraint+ alpha[n] ~ ty, do not unify alpha := ty if there are any given equalities+ between levels 'n' and 'l'.++ Exactly what is a "given equality" for the purpose of (UNTOUCHABLE)?+ Answer: see Note [Tracking Given equalities] in GHC.Tc.Solver.Monad++3. (TYVAR-TV) Unifying TyVarTvs and CycleBreakerTvs+ This precondition looks at the MetaInfo of the unification variable:++ * TyVarTv: When considering alpha{tyv} ~ ty, if alpha{tyv} is a+ TyVarTv it can only unify with a type variable, not with a+ structured type. So if 'ty' is a structured type, such as (Maybe x),+ don't unify.++ * CycleBreakerTv: never unified, except by restoreTyVarCycles.+++Needless to say, all three have wrinkles:++* (SKOL-ESC) Promotion. Given alpha[n] ~ ty, what if beta[k] is free+ in 'ty', where beta is a unification variable, and k>n? 'beta'+ stands for a monotype, and since it is part of a level-n type+ (equal to alpha[n]), we must /promote/ beta to level n. Just make+ up a fresh gamma[n], and unify beta[k] := gamma[n].++* (TYVAR-TV) Unification variables. Suppose alpha[tyv,n] is a level-n+ TyVarTv (see Note [Signature skolems] in GHC.Tc.Types.TcType)? Now+ consider alpha[tyv,n] ~ Bool. We don't want to unify because that+ would break the TyVarTv invariant.++ What about alpha[tyv,n] ~ beta[tau,n], where beta is an ordinary+ TauTv? Again, don't unify, because beta might later be unified+ with, say Bool. (If levels permit, we reverse the orientation here;+ see Note [TyVar/TyVar orientation].)++* (UNTOUCHABLE) Untouchability. When considering (alpha[n] ~ ty), how+ do we know whether there are any given equalities between level n+ and the ambient level? We answer in two ways:++ * In the eager unifier, we only unify if l=n. If not, alpha may be+ untouchable, and defer to the constraint solver. This check is+ made in GHC.Tc.Utils.uUnifilledVar2, in the guard+ isTouchableMetaTyVar.++ * In the constraint solver, we track where Given equalities occur+ and use that to guard unification in GHC.Tc.Solver.Canonical.unifyTest+ More details in Note [Tracking Given equalities] in GHC.Tc.Solver.Monad++ Historical note: in the olden days (pre 2021) the constraint solver+ also used to unify only if l=n. Equalities were "floated" out of the+ implication in a separate step, so that they would become touchable.+ But the float/don't-float question turned out to be very delicate,+ as you can see if you look at the long series of Notes associated with+ GHC.Tc.Solver.floatEqualities, around Nov 2020. It's much easier+ to unify in-place, with no floating.++Note [TyVar/TyVar orientation]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Given (a ~ b), should we orient the CEqCan as (a~b) or (b~a)? This is a surprisingly tricky question! This is invariant (TyEq:TV). -The question is answered by swapOverTyVars, which is use+The question is answered by swapOverTyVars, which is used - in the eager unifier, in GHC.Tc.Utils.Unify.uUnfilledVar1- - in the constraint solver, in GHC.Tc.Solver.Canonical.canEqTyVarHomo+ - in the constraint solver, in GHC.Tc.Solver.Canonical.canEqCanLHS2 First note: only swap if you have to! See Note [Avoid unnecessary swaps]@@ -1531,25 +1640,23 @@ looks for meta tyvars on the left Tie-breaking rules for MetaTvs:- - FlatMetaTv = 4: always put on the left.- See Note [Fmv Orientation Invariant]-- NB: FlatMetaTvs always have the current level, never an- outer one. So nothing can be deeper than a FlatMetaTv.+ - CycleBreakerTv: This is essentially a stand-in for another type;+ it's untouchable and should have the same priority as a skolem: 0. - - TauTv = 3: if we have tyv_tv ~ tau_tv,- put tau_tv on the left because there are fewer- restrictions on updating TauTvs. Or to say it another- way, then we won't lose the TyVarTv flag+ - TyVarTv: These can unify only with another tyvar, but we can't unify+ a TyVarTv with a TauTv, because then the TyVarTv could (transitively)+ get a non-tyvar type. So give these a low priority: 1. - - TyVarTv = 2: remember, flat-skols are *only* updated by- the unflattener, never unified, so TyVarTvs come next+ - TauTv: This is the common case; we want these on the left so that they+ can be written to: 2. - - FlatSkolTv = 1: put on the left in preference to a SkolemTv.- See Note [Eliminate flat-skols]+ - 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+ GHC.Runtime.Heap.Inspect. * Names. If the level and priority comparisons are all- equal, try to eliminate a TyVars with a System Name in+ equal, try to eliminate a TyVar with a System Name in favour of ones with a Name derived from a user type signature * Age. At one point in the past we tried to break any remaining@@ -1602,64 +1709,6 @@ See #15009 for an further analysis of why "deepest on the left" is a good plan. -Note [Fmv Orientation Invariant]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~- * We always orient a constraint- fmv ~ alpha- with fmv on the left, even if alpha is- a touchable unification variable--Reason: doing it the other way round would unify alpha:=fmv, but that-really doesn't add any info to alpha. But a later constraint alpha ~-Int might unlock everything. Comment:9 of #12526 gives a detailed-example.--WARNING: I've gone to and fro on this one several times.-I'm now pretty sure that unifying alpha:=fmv is a bad idea!-So orienting with fmvs on the left is a good thing.--This example comes from IndTypesPerfMerge. (Others include-T10226, T10009.)- From the ambiguity check for- f :: (F a ~ a) => a- we get:- [G] F a ~ a- [WD] F alpha ~ alpha, alpha ~ a-- From Givens we get- [G] F a ~ fsk, fsk ~ a-- Now if we flatten we get- [WD] alpha ~ fmv, F alpha ~ fmv, alpha ~ a-- Now, if we unified alpha := fmv, we'd get- [WD] F fmv ~ fmv, [WD] fmv ~ a- And now we are stuck.--So instead the Fmv Orientation Invariant puts the fmv on the-left, giving- [WD] fmv ~ alpha, [WD] F alpha ~ fmv, [WD] alpha ~ a-- Now we get alpha:=a, and everything works out--Note [Eliminate flat-skols]-~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we have [G] Num (F [a])-then we flatten to- [G] Num fsk- [G] F [a] ~ fsk-where fsk is a flatten-skolem (FlatSkolTv). Suppose we have- type instance F [a] = a-then we'll reduce the second constraint to- [G] a ~ fsk-and then replace all uses of 'a' with fsk. That's bad because-in error messages instead of saying 'a' we'll say (F [a]). In all-places, including those where the programmer wrote 'a' in the first-place. Very confusing! See #7862.--Solution: re-orient a~fsk to fsk~a, so that we preferentially eliminate-the fsk.- Note [Avoid unnecessary swaps] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If we swap without actually improving matters, we can get an infinite loop.@@ -1673,8 +1722,8 @@ inert item: c ~ a And now the cycle just repeats -Note [Eliminate younger unification variables]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Historical Note [Eliminate younger unification variables]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Given a choice of unifying alpha := beta or beta := alpha we try, if possible, to eliminate the "younger" one, as determined@@ -1688,36 +1737,11 @@ It's simple to implement (see nicer_to_update_tv2 in swapOverTyVars). But, to my surprise, it didn't seem to make any significant difference to the compiler's performance, so I didn't take it any further. Still-it seemed to too nice to discard altogether, so I'm leaving these+it seemed too nice to discard altogether, so I'm leaving these notes. SLPJ Jan 18.--} --- @trySpontaneousSolve wi@ solves equalities where one side is a--- touchable unification variable.--- Returns True <=> spontaneous solve happened-canSolveByUnification :: TcLevel -> TcTyVar -> TcType -> Bool-canSolveByUnification tclvl tv xi- | isTouchableMetaTyVar tclvl tv- = case metaTyVarInfo tv of- TyVarTv -> is_tyvar xi- _ -> True-- | otherwise -- Untouchable- = False- where- is_tyvar xi- = case tcGetTyVar_maybe xi of- Nothing -> False- Just tv -> case tcTyVarDetails tv of- MetaTv { mtv_info = info }- -> case info of- TyVarTv -> True- _ -> False- SkolemTv {} -> True- RuntimeUnk -> True--{- Note [Prevent unification with type families]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Note [Prevent unification with type families]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We prevent unification with type families because of an uneasy compromise. It's perfectly sound to unify with type families, and it even improves the error messages in the testsuite. It also modestly improves performance, at@@ -1725,8 +1749,7 @@ Here is the problem: Suppose we have (F ty) where we also have [G] F ty ~ a. What do we do? Do we reduce F? Or do we use the given? Hard to know what's best. GHC reduces. This is a disaster for T3064, where the type's size-spirals out of control during reduction. (We're not helped by the fact that-the flattener re-flattens all the arguments every time around.) If we prevent+spirals out of control during reduction. If we prevent unification with type families, then the solver happens to use the equality before expanding the type family. @@ -1734,8 +1757,11 @@ extra, unnecessary check. But we retain it for now as it seems to work better in practice. -Note [Refactoring hazard: checkTauTvUpdate]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Revisited in Nov '20, along with removing flattening variables. Problem+is still present, and the solution (NoTypeFamilies) is still the same.++Note [Refactoring hazard: metaTyVarUpdateOK]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I (Richard E.) have a sad story about refactoring this code, retained here to prevent others (or a future me!) from falling into the same traps. @@ -1819,35 +1845,6 @@ causing this wibble in behavior seen here. -} -data LookupTyVarResult -- The result of a lookupTcTyVar call- = Unfilled TcTyVarDetails -- SkolemTv or virgin MetaTv- | Filled TcType--lookupTcTyVar :: TcTyVar -> TcM LookupTyVarResult-lookupTcTyVar tyvar- | MetaTv { mtv_ref = ref } <- details- = do { meta_details <- readMutVar ref- ; case meta_details of- Indirect ty -> return (Filled ty)- Flexi -> do { is_touchable <- isTouchableTcM tyvar- -- Note [Unifying untouchables]- ; if is_touchable then- return (Unfilled details)- else- return (Unfilled vanillaSkolemTv) } }- | otherwise- = return (Unfilled details)- where- details = tcTyVarDetails tyvar--{--Note [Unifying untouchables]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We treat an untouchable type variable as if it was a skolem. That-ensures it won't unify with anything. It's a slight hack, because-we return a made-up TcTyVarDetails, but I think it works smoothly.--}- -- | Breaks apart a function kind into its pieces. matchExpectedFunKind :: Outputable fun@@ -1926,162 +1923,170 @@ -} -data MetaTyVarUpdateResult a- = MTVU_OK a- | MTVU_Bad -- Forall, predicate, or type family- | MTVU_HoleBlocker -- Blocking coercion hole+data CheckTyEqResult+ = CTE_OK+ | CTE_Bad -- Forall, predicate, or type family+ | CTE_HoleBlocker -- Blocking coercion hole -- See Note [Equalities with incompatible kinds] in "GHC.Tc.Solver.Canonical"- | MTVU_Occurs- deriving (Functor)+ | CTE_Occurs -instance Applicative MetaTyVarUpdateResult where- pure = MTVU_OK- (<*>) = ap+instance S.Semigroup CheckTyEqResult where+ CTE_OK <> x = x+ x <> _ = x -instance Monad MetaTyVarUpdateResult where- MTVU_OK x >>= k = k x- MTVU_Bad >>= _ = MTVU_Bad- MTVU_HoleBlocker >>= _ = MTVU_HoleBlocker- MTVU_Occurs >>= _ = MTVU_Occurs+instance Monoid CheckTyEqResult where+ mempty = CTE_OK -instance Outputable a => Outputable (MetaTyVarUpdateResult a) where- ppr (MTVU_OK a) = text "MTVU_OK" <+> ppr a- ppr MTVU_Bad = text "MTVU_Bad"- ppr MTVU_HoleBlocker = text "MTVU_HoleBlocker"- ppr MTVU_Occurs = text "MTVU_Occurs"+instance Outputable CheckTyEqResult where+ ppr CTE_OK = text "CTE_OK"+ ppr CTE_Bad = text "CTE_Bad"+ ppr CTE_HoleBlocker = text "CTE_HoleBlocker"+ ppr CTE_Occurs = text "CTE_Occurs" -occCheckForErrors :: DynFlags -> TcTyVar -> Type -> MetaTyVarUpdateResult ()--- Just for error-message generation; so we return MetaTyVarUpdateResult+occCheckForErrors :: DynFlags -> TcTyVar -> Type -> CheckTyEqResult+-- Just for error-message generation; so we return CheckTyEqResult -- so the caller can report the right kind of error -- Check whether -- a) the given variable occurs in the given type. -- b) there is a forall in the type (unless we have -XImpredicativeTypes) occCheckForErrors dflags tv ty- = case mtvu_check dflags True tv ty of- MTVU_OK _ -> MTVU_OK ()- MTVU_Bad -> MTVU_Bad- MTVU_HoleBlocker -> MTVU_HoleBlocker- MTVU_Occurs -> case occCheckExpand [tv] ty of- Nothing -> MTVU_Occurs- Just _ -> MTVU_OK ()+ = case checkTyVarEq dflags YesTypeFamilies tv ty of+ CTE_Occurs -> case occCheckExpand [tv] ty of+ Nothing -> CTE_Occurs+ Just _ -> CTE_OK+ other -> other -----------------metaTyVarUpdateOK :: DynFlags- -> TcTyVar -- tv :: k1- -> TcType -- ty :: k2- -> MetaTyVarUpdateResult TcType -- possibly-expanded ty--- (metaTyVarUpdateOK tv ty)--- Checks that the equality tv~ty is OK to be used to rewrite--- other equalities. Equivalently, checks the conditions for CTyEqCan--- (a) that tv doesn't occur in ty (occurs check)--- (b) that ty does not have any foralls--- (in the impredicative case), or type functions--- (c) that ty does not have any blocking coercion holes--- See Note [Equalities with incompatible kinds] in "GHC.Tc.Solver.Canonical"------ Used in two places:--- - In the eager unifier: uUnfilledVar2--- - In the canonicaliser: GHC.Tc.Solver.Canonical.canEqTyVar2--- Note that in the latter case tv is not necessarily a meta-tyvar,--- despite the name of this function.+data AreTypeFamiliesOK = YesTypeFamilies+ | NoTypeFamilies+ deriving Eq --- We have two possible outcomes:--- (1) Return the type to update the type variable with,--- [we know the update is ok]--- (2) Return Nothing,--- [the update might be dodgy]------ Note that "Nothing" does not mean "definite error". For example--- type family F a--- type instance F Int = Int--- consider--- a ~ F a--- This is perfectly reasonable, if we later get a ~ Int. For now, though,--- we return Nothing, leaving it to the later constraint simplifier to--- sort matters out.------ See Note [Refactoring hazard: checkTauTvUpdate]+instance Outputable AreTypeFamiliesOK where+ ppr YesTypeFamilies = text "YesTypeFamilies"+ ppr NoTypeFamilies = text "NoTypeFamilies" -metaTyVarUpdateOK dflags tv ty- = case mtvu_check dflags False tv ty of- -- False <=> type families not ok- -- See Note [Prevent unification with type families]- MTVU_OK _ -> MTVU_OK ty- MTVU_Bad -> MTVU_Bad -- forall, predicate, type function- MTVU_HoleBlocker -> MTVU_HoleBlocker -- coercion hole- MTVU_Occurs -> case occCheckExpand [tv] ty of- Just expanded_ty -> MTVU_OK expanded_ty- Nothing -> MTVU_Occurs+checkTyVarEq :: DynFlags -> AreTypeFamiliesOK -> TcTyVar -> TcType -> CheckTyEqResult+checkTyVarEq dflags ty_fam_ok tv ty+ = inline checkTypeEq dflags ty_fam_ok (TyVarLHS tv) ty+ -- inline checkTypeEq so that the `case`s over the CanEqLHS get blasted away -mtvu_check :: DynFlags -> Bool -> TcTyVar -> TcType -> MetaTyVarUpdateResult ()--- Checks the invariants for CTyEqCan. In particular:+checkTyFamEq :: DynFlags+ -> TyCon -- type function+ -> [TcType] -- args, exactly saturated+ -> TcType -- RHS+ -> CheckTyEqResult+checkTyFamEq dflags fun_tc fun_args ty+ = inline checkTypeEq dflags YesTypeFamilies (TyFamLHS fun_tc fun_args) ty+ -- inline checkTypeEq so that the `case`s over the CanEqLHS get blasted away++checkTypeEq :: DynFlags -> AreTypeFamiliesOK -> CanEqLHS -> TcType+ -> CheckTyEqResult+-- Checks the invariants for CEqCan. In particular: -- (a) a forall type (forall a. blah) -- (b) a predicate type (c => ty) -- (c) a type family; see Note [Prevent unification with type families] -- (d) a blocking coercion hole--- (e) an occurrence of the type variable (occurs check)+-- (e) an occurrence of the LHS (occurs check) --+-- Note that an occurs-check does not mean "definite error". For example+-- type family F a+-- type instance F Int = Int+-- consider+-- b0 ~ F b0+-- This is perfectly reasonable, if we later get b0 ~ Int. But we+-- certainly can't unify b0 := F b0+-- -- For (a), (b), and (c) we check only the top level of the type, NOT -- inside the kinds of variables it mentions. For (d) we look deeply--- in coercions, and for (e) we do look in the kinds of course.--mtvu_check dflags ty_fam_ok tv ty- = fast_check ty+-- in coercions when the LHS is a tyvar (but skip coercions for type family+-- LHSs), and for (e) see Note [CEqCan occurs check] in GHC.Tc.Types.Constraint.+--+-- checkTypeEq is called from+-- * checkTyFamEq, checkTyVarEq (which inline it to specialise away the+-- case-analysis on 'lhs')+-- * checkEqCanLHSFinish, which does not know the form of 'lhs'+checkTypeEq dflags ty_fam_ok lhs ty+ = go ty where- ok :: MetaTyVarUpdateResult ()- ok = MTVU_OK ()- -- The GHCi runtime debugger does its type-matching with -- unification variables that can unify with a polytype -- or a TyCon that would usually be disallowed by bad_tc -- See Note [RuntimeUnkTv] in GHC.Runtime.Heap.Inspect- ghci_tv = case tcTyVarDetails tv of- MetaTv { mtv_info = RuntimeUnkTv } -> True- _ -> False+ ghci_tv+ | TyVarLHS tv <- lhs+ , MetaTv { mtv_info = RuntimeUnkTv } <- tcTyVarDetails tv+ = True - fast_check :: TcType -> MetaTyVarUpdateResult ()- fast_check (TyVarTy tv')- | tv == tv' = MTVU_Occurs- | otherwise = fast_check_occ (tyVarKind tv')- -- See Note [Occurrence checking: look inside kinds]- -- in GHC.Core.Type+ | otherwise+ = False - fast_check (TyConApp tc tys)- | bad_tc tc, not ghci_tv = MTVU_Bad- | otherwise = mapM fast_check tys >> ok- fast_check (LitTy {}) = ok- fast_check (FunTy{ft_af = af, ft_mult = w, ft_arg = a, ft_res = r})+ go :: TcType -> CheckTyEqResult+ go (TyVarTy tv') = go_tv tv'+ go (TyConApp tc tys) = go_tc tc tys+ go (LitTy {}) = CTE_OK+ go (FunTy{ft_af = af, ft_mult = w, ft_arg = a, ft_res = r}) | InvisArg <- af- , not ghci_tv = MTVU_Bad- | otherwise = fast_check w >> fast_check a >> fast_check r- fast_check (AppTy fun arg) = fast_check fun >> fast_check arg- fast_check (CastTy ty co) = fast_check ty >> fast_check_co co- fast_check (CoercionTy co) = fast_check_co co- fast_check (ForAllTy (Bndr tv' _) ty)- | not ghci_tv = MTVU_Bad- | tv == tv' = ok- | otherwise = do { fast_check_occ (tyVarKind tv')- ; fast_check_occ ty }- -- Under a forall we look only for occurrences of- -- the type variable+ , not ghci_tv = CTE_Bad+ | otherwise = go w S.<> go a S.<> go r+ go (AppTy fun arg) = go fun S.<> go arg+ go (CastTy ty co) = go ty S.<> go_co co+ go (CoercionTy co) = go_co co+ go (ForAllTy (Bndr tv' _) ty)+ | not ghci_tv = CTE_Bad+ | otherwise = case lhs of+ TyVarLHS tv | tv == tv' -> CTE_OK+ | otherwise -> go_occ tv (tyVarKind tv') S.<> go ty+ _ -> go ty + go_tv :: TcTyVar -> CheckTyEqResult+ -- this slightly peculiar way of defining this means+ -- we don't have to evaluate this `case` at every variable+ -- occurrence+ go_tv = case lhs of+ TyVarLHS tv -> \ tv' -> if tv == tv'+ then CTE_Occurs+ else go_occ tv (tyVarKind tv')+ TyFamLHS {} -> \ _tv' -> CTE_OK+ -- See Note [Occurrence checking: look inside kinds] in GHC.Core.Type+ -- For kinds, we only do an occurs check; we do not worry -- about type families or foralls -- See Note [Checking for foralls]- fast_check_occ k | tv `elemVarSet` tyCoVarsOfType k = MTVU_Occurs- | otherwise = ok+ go_occ tv k | tv `elemVarSet` tyCoVarsOfType k = CTE_Occurs+ | otherwise = CTE_OK + go_tc :: TyCon -> [TcType] -> CheckTyEqResult+ -- this slightly peculiar way of defining this means+ -- we don't have to evaluate this `case` at every tyconapp+ go_tc = case lhs of+ TyVarLHS {} -> \ tc tys ->+ if | good_tc tc -> mconcat (map go tys)+ | otherwise -> CTE_Bad+ TyFamLHS fam_tc fam_args -> \ tc tys ->+ if | tcEqTyConApps fam_tc fam_args tc tys -> CTE_Occurs+ | good_tc tc -> mconcat (map go tys)+ | otherwise -> CTE_Bad++ -- no bother about impredicativity in coercions, as they're -- inferred- fast_check_co co | not (gopt Opt_DeferTypeErrors dflags)- , badCoercionHoleCo co = MTVU_HoleBlocker- -- Wrinkle (4b) in "GHC.Tc.Solver.Canonical" Note [Equalities with incompatible kinds]+ go_co co | not (gopt Opt_DeferTypeErrors dflags)+ , hasCoercionHoleCo co+ = CTE_HoleBlocker -- Wrinkle (2) in GHC.Tc.Solver.Canonical+ -- See GHC.Tc.Solver.Canonical Note [Equalities with incompatible kinds]+ -- Wrinkle (2) about this case in general, Wrinkle (4b) about the check for+ -- deferred type errors. - | tv `elemVarSet` tyCoVarsOfCo co = MTVU_Occurs- | otherwise = ok+ | TyVarLHS tv <- lhs+ , tv `elemVarSet` tyCoVarsOfCo co+ = CTE_Occurs - bad_tc :: TyCon -> Bool- bad_tc tc- | not (isTauTyCon tc) = True- | not (ty_fam_ok || isFamFreeTyCon tc) = True- | otherwise = False+ -- Don't check coercions for type families; see commentary at top of function+ | otherwise+ = CTE_OK++ good_tc :: TyCon -> Bool+ good_tc+ | ghci_tv = \ _tc -> True+ | otherwise = \ tc -> isTauTyCon tc &&+ (ty_fam_ok == YesTypeFamilies || isFamFreeTyCon tc)
compiler/GHC/Tc/Utils/Zonk.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -Wno-incomplete-record-updates #-} @@ -625,7 +626,7 @@ , psb_dir = dir })) = do { id' <- zonkIdBndr env id ; (env1, lpat') <- zonkPat env lpat- ; let details' = zonkPatSynDetails env1 details+ ; details' <- zonkPatSynDetails env1 details ; (_env2, dir') <- zonkPatSynDir env1 dir ; return $ PatSynBind x $ bind { psb_id = L loc id'@@ -635,14 +636,18 @@ zonkPatSynDetails :: ZonkEnv -> HsPatSynDetails GhcTc- -> HsPatSynDetails GhcTc-zonkPatSynDetails env (PrefixCon as)- = PrefixCon (map (zonkLIdOcc env) as)+ -> TcM (HsPatSynDetails GhcTc)+zonkPatSynDetails env (PrefixCon _ as)+ = pure $ PrefixCon noTypeArgs (map (zonkLIdOcc env) as) zonkPatSynDetails env (InfixCon a1 a2)- = InfixCon (zonkLIdOcc env a1) (zonkLIdOcc env a2)+ = pure $ InfixCon (zonkLIdOcc env a1) (zonkLIdOcc env a2) zonkPatSynDetails env (RecCon flds)- = RecCon (map (fmap (zonkLIdOcc env)) flds)+ = RecCon <$> mapM (zonkPatSynField env) flds +zonkPatSynField :: ZonkEnv -> RecordPatSynField GhcTc -> TcM (RecordPatSynField GhcTc)+zonkPatSynField env (RecordPatSynField x y) =+ RecordPatSynField <$> zonkFieldOcc env x <*> pure (zonkLIdOcc env y)+ zonkPatSynDir :: ZonkEnv -> HsPatSynDir GhcTc -> TcM (ZonkEnv, HsPatSynDir GhcTc) zonkPatSynDir env Unidirectional = return (env, Unidirectional)@@ -731,8 +736,15 @@ = ASSERT2( isNothing (isDataConId_maybe id), ppr id ) return (HsVar x (L l (zonkIdOcc env id))) -zonkExpr env (HsUnboundVar v occ)- = return (HsUnboundVar (zonkIdOcc env v) occ)+zonkExpr env (HsUnboundVar her occ)+ = do her' <- zonk_her her+ return (HsUnboundVar her' occ)+ where+ zonk_her :: HoleExprRef -> TcM HoleExprRef+ zonk_her (HER ref ty u)+ = do updMutVarM ref (zonkEvTerm env)+ ty' <- zonkTcTypeToTypeX env ty+ return (HER ref ty' u) zonkExpr env (HsRecFld _ (Ambiguous v occ)) = return (HsRecFld noExtField (Ambiguous (zonkIdOcc env v) occ))@@ -1465,9 +1477,9 @@ --------------------------- zonkConStuff :: ZonkEnv -> HsConPatDetails GhcTc -> TcM (ZonkEnv, HsConPatDetails GhcTc)-zonkConStuff env (PrefixCon pats)+zonkConStuff env (PrefixCon tyargs pats) = do { (env', pats') <- zonkPats env pats- ; return (env', PrefixCon pats') }+ ; return (env', PrefixCon tyargs pats') } zonkConStuff env (InfixCon p1 p2) = do { (env1, p1') <- zonkPat env p1
compiler/GHC/Tc/Validity.hs view
@@ -2263,12 +2263,6 @@ -> [TcType] -- LHS patterns -> Type -- RHS -> TcM ()--- We do these binder checks now, in tcFamTyPatsAndGen, rather--- than later, in checkValidFamEqn, for two reasons:--- - We have the implicitly and explicitly--- bound type variables conveniently to hand--- - If implicit variables are out of scope it may--- cause a crash; notably in tcConDecl in tcDataFamInstDecl checkFamPatBinders fam_tc qtvs pats rhs = do { traceTc "checkFamPatBinders" $ vcat [ debugPprType (mkTyConApp fam_tc pats)
compiler/GHC/ThToHs.hs view
@@ -409,10 +409,10 @@ ; returnJustL $ Hs.ValD noExtField $ PatSynBind noExtField $ PSB noExtField nm' args' pat' dir' } where- cvtArgs (TH.PrefixPatSyn args) = Hs.PrefixCon <$> mapM vNameL args+ cvtArgs (TH.PrefixPatSyn args) = Hs.PrefixCon noTypeArgs <$> mapM vNameL args cvtArgs (TH.InfixPatSyn a1 a2) = Hs.InfixCon <$> vNameL a1 <*> vNameL a2 cvtArgs (TH.RecordPatSyn sels)- = do { sels' <- mapM vNameL sels+ = do { sels' <- mapM (fmap (\ (L li i) -> FieldOcc noExtField (L li i)) . vNameL) sels ; vars' <- mapM (vNameL . mkNameS . nameBase) sels ; return $ Hs.RecCon $ zipWith RecordPatSynField sels' vars' } @@ -578,7 +578,7 @@ cvtConstr (NormalC c strtys) = do { c' <- cNameL c ; tys' <- mapM cvt_arg strtys- ; returnL $ mkConDeclH98 c' Nothing Nothing (PrefixCon (map hsLinear tys')) }+ ; returnL $ mkConDeclH98 c' Nothing Nothing (PrefixCon noTypeArgs (map hsLinear tys')) } cvtConstr (RecC c varstrtys) = do { c' <- cNameL c@@ -1292,12 +1292,14 @@ = do { p' <- cvtPat p ; unboxedSumChecks alt arity ; return $ SumPat noExtField p' alt arity }-cvtp (ConP s ps) = do { s' <- cNameL s; ps' <- cvtPats ps+cvtp (ConP s ts ps) = do { s' <- cNameL s+ ; ps' <- cvtPats ps+ ; ts' <- mapM cvtType ts ; let pps = map (parenthesizePat appPrec) ps' ; return $ ConPat { pat_con_ext = noExtField , pat_con = s'- , pat_args = PrefixCon pps+ , pat_args = PrefixCon (map mkHsPatSigType ts') pps } } cvtp (InfixP p1 s p2) = do { s' <- cNameL s; p1' <- cvtPat p1; p2' <- cvtPat p2
compiler/GHC/Types/Name/Shape.hs view
@@ -183,13 +183,18 @@ -- for type constructors, where it is sufficient to substitute the 'availName' -- to induce a substitution on 'availNames'. substNameAvailInfo :: HscEnv -> ShNameSubst -> AvailInfo -> IO AvailInfo-substNameAvailInfo _ env (Avail n) = return (Avail (substName env n))-substNameAvailInfo hsc_env env (AvailTC n ns fs) =+substNameAvailInfo _ env (Avail (NormalGreName n)) = return (Avail (NormalGreName (substName env n)))+substNameAvailInfo _ env (Avail (FieldGreName fl)) =+ return (Avail (FieldGreName fl { flSelector = substName env (flSelector fl) }))+substNameAvailInfo hsc_env env (AvailTC n ns) = let mb_mod = fmap nameModule (lookupNameEnv env n)- in AvailTC (substName env n)- <$> mapM (initIfaceLoad hsc_env . setNameModule mb_mod) ns- <*> mapM (setNameFieldSelector hsc_env mb_mod) fs+ in AvailTC (substName env n) <$> mapM (setNameGreName hsc_env mb_mod) ns +setNameGreName :: HscEnv -> Maybe Module -> GreName -> IO GreName+setNameGreName hsc_env mb_mod gname = case gname of+ NormalGreName n -> NormalGreName <$> initIfaceLoad hsc_env (setNameModule mb_mod n)+ FieldGreName fl -> FieldGreName <$> setNameFieldSelector hsc_env mb_mod fl+ -- | Set the 'Module' of a 'FieldSelector' setNameFieldSelector :: HscEnv -> Maybe Module -> FieldLabel -> IO FieldLabel setNameFieldSelector _ Nothing f = return f@@ -235,8 +240,8 @@ -- with only name holes from @flexi@ unifiable (all other name holes rigid.) uAvailInfo :: ModuleName -> ShNameSubst -> AvailInfo -> AvailInfo -> Either SDoc ShNameSubst-uAvailInfo flexi subst (Avail n1) (Avail n2) = uName flexi subst n1 n2-uAvailInfo flexi subst (AvailTC n1 _ _) (AvailTC n2 _ _) = uName flexi subst n1 n2+uAvailInfo flexi subst (Avail (NormalGreName n1)) (Avail (NormalGreName n2)) = uName flexi subst n1 n2+uAvailInfo flexi subst (AvailTC n1 _) (AvailTC n2 _) = uName flexi subst n1 n2 uAvailInfo _ _ a1 a2 = Left $ text "While merging export lists, could not combine" <+> ppr a1 <+> text "with" <+> ppr a2 <+> parens (text "one is a type, the other is a plain identifier")
compiler/GHC/Unit/Finder.hs view
@@ -29,9 +29,6 @@ findObjectLinkableMaybe, findObjectLinkable, - cannotFindModule,- cannotFindInterface,- ) where #include "GhclibHsVersions.h"@@ -198,14 +195,14 @@ findExposedPackageModule hsc_env mod_name mb_pkg = findLookupResult hsc_env $ lookupModuleWithSuggestions- (unitState (hsc_dflags hsc_env)) mod_name mb_pkg+ (hsc_units hsc_env) mod_name mb_pkg findExposedPluginPackageModule :: HscEnv -> ModuleName -> IO FindResult findExposedPluginPackageModule hsc_env mod_name = findLookupResult hsc_env $ lookupPluginModuleWithSuggestions- (unitState (hsc_dflags hsc_env)) mod_name Nothing+ (hsc_units hsc_env) mod_name Nothing findLookupResult :: HscEnv -> LookupResult -> IO FindResult findLookupResult hsc_env r = case r of@@ -354,14 +351,10 @@ -- | Search for a module in external packages only. findPackageModule :: HscEnv -> InstalledModule -> IO InstalledFindResult findPackageModule hsc_env mod = do- let- dflags = hsc_dflags hsc_env- pkg_id = moduleUnit mod- pkgstate = unitState dflags- --- case lookupUnitId pkgstate pkg_id of+ let pkg_id = moduleUnit mod+ case lookupUnitId (hsc_units hsc_env) pkg_id of Nothing -> return (InstalledNoPackage pkg_id)- Just pkg_conf -> findPackageModule_ hsc_env mod pkg_conf+ Just u -> findPackageModule_ hsc_env mod u -- | Look up the interface file associated with module @mod@. This function -- requires a few invariants to be upheld: (1) the 'Module' in question must@@ -617,239 +610,3 @@ -- We used to look for _stub.o files here, but that was a bug (#706) -- Now GHC merges the stub.o into the main .o (#3687) --- -------------------------------------------------------------------------------- Error messages--cannotFindModule :: DynFlags -> ModuleName -> FindResult -> SDoc-cannotFindModule dflags mod res = pprWithUnitState unit_state $- cantFindErr (sLit cannotFindMsg)- (sLit "Ambiguous module name")- dflags mod res- where- unit_state = unitState dflags- cannotFindMsg =- case res of- NotFound { fr_mods_hidden = hidden_mods- , fr_pkgs_hidden = hidden_pkgs- , fr_unusables = unusables }- | not (null hidden_mods && null hidden_pkgs && null unusables)- -> "Could not load module"- _ -> "Could not find module"--cannotFindInterface :: DynFlags -> ModuleName -> InstalledFindResult -> SDoc-cannotFindInterface = cantFindInstalledErr (sLit "Failed to load interface for")- (sLit "Ambiguous interface for")--cantFindErr :: PtrString -> PtrString -> DynFlags -> ModuleName -> FindResult- -> SDoc-cantFindErr _ multiple_found _ mod_name (FoundMultiple mods)- | Just pkgs <- unambiguousPackages- = hang (ptext multiple_found <+> quotes (ppr mod_name) <> colon) 2 (- sep [text "it was found in multiple packages:",- hsep (map ppr pkgs) ]- )- | otherwise- = hang (ptext multiple_found <+> quotes (ppr mod_name) <> colon) 2 (- vcat (map pprMod mods)- )- where- unambiguousPackages = foldl' unambiguousPackage (Just []) mods- unambiguousPackage (Just xs) (m, ModOrigin (Just _) _ _ _)- = Just (moduleUnit m : xs)- unambiguousPackage _ _ = Nothing-- pprMod (m, o) = text "it is bound as" <+> ppr m <+>- text "by" <+> pprOrigin m o- pprOrigin _ ModHidden = panic "cantFindErr: bound by mod hidden"- pprOrigin _ (ModUnusable _) = panic "cantFindErr: bound by mod unusable"- pprOrigin m (ModOrigin e res _ f) = sep $ punctuate comma (- if e == Just True- then [text "package" <+> ppr (moduleUnit m)]- else [] ++- map ((text "a reexport in package" <+>)- .ppr.mkUnit) res ++- if f then [text "a package flag"] else []- )--cantFindErr cannot_find _ dflags mod_name find_result- = ptext cannot_find <+> quotes (ppr mod_name)- $$ more_info- where- pkgs = unitState dflags- home_unit = mkHomeUnitFromFlags dflags- more_info- = case find_result of- NoPackage pkg- -> text "no unit id matching" <+> quotes (ppr pkg) <+>- text "was found"-- NotFound { fr_paths = files, fr_pkg = mb_pkg- , fr_mods_hidden = mod_hiddens, fr_pkgs_hidden = pkg_hiddens- , fr_unusables = unusables, fr_suggestions = suggest }- | Just pkg <- mb_pkg, not (isHomeUnit home_unit pkg)- -> not_found_in_package pkg files-- | not (null suggest)- -> pp_suggestions suggest $$ tried_these files dflags-- | null files && null mod_hiddens &&- null pkg_hiddens && null unusables- -> text "It is not a module in the current program, or in any known package."-- | otherwise- -> vcat (map pkg_hidden pkg_hiddens) $$- vcat (map mod_hidden mod_hiddens) $$- vcat (map unusable unusables) $$- tried_these files dflags-- _ -> panic "cantFindErr"-- build_tag = waysBuildTag (ways dflags)-- not_found_in_package pkg files- | build_tag /= ""- = let- build = if build_tag == "p" then "profiling"- else "\"" ++ build_tag ++ "\""- in- text "Perhaps you haven't installed the " <> text build <>- text " libraries for package " <> quotes (ppr pkg) <> char '?' $$- tried_these files dflags-- | otherwise- = text "There are files missing in the " <> quotes (ppr pkg) <>- text " package," $$- text "try running 'ghc-pkg check'." $$- tried_these files dflags-- pkg_hidden :: Unit -> SDoc- pkg_hidden uid =- text "It is a member of the hidden package"- <+> quotes (ppr uid)- --FIXME: we don't really want to show the unit id here we should- -- show the source package id or installed package id if it's ambiguous- <> dot $$ pkg_hidden_hint uid- pkg_hidden_hint uid- | gopt Opt_BuildingCabalPackage dflags- = let pkg = expectJust "pkg_hidden" (lookupUnit pkgs uid)- in text "Perhaps you need to add" <+>- quotes (ppr (unitPackageName pkg)) <+>- text "to the build-depends in your .cabal file."- | Just pkg <- lookupUnit pkgs uid- = text "You can run" <+>- quotes (text ":set -package " <> ppr (unitPackageName pkg)) <+>- text "to expose it." $$- text "(Note: this unloads all the modules in the current scope.)"- | otherwise = Outputable.empty-- mod_hidden pkg =- text "it is a hidden module in the package" <+> quotes (ppr pkg)-- unusable (pkg, reason)- = text "It is a member of the package"- <+> quotes (ppr pkg)- $$ pprReason (text "which is") reason-- pp_suggestions :: [ModuleSuggestion] -> SDoc- pp_suggestions sugs- | null sugs = Outputable.empty- | otherwise = hang (text "Perhaps you meant")- 2 (vcat (map pp_sugg sugs))-- -- NB: Prefer the *original* location, and then reexports, and then- -- package flags when making suggestions. ToDo: if the original package- -- also has a reexport, prefer that one- pp_sugg (SuggestVisible m mod o) = ppr m <+> provenance o- where provenance ModHidden = Outputable.empty- provenance (ModUnusable _) = Outputable.empty- provenance (ModOrigin{ fromOrigUnit = e,- fromExposedReexport = res,- fromPackageFlag = f })- | Just True <- e- = parens (text "from" <+> ppr (moduleUnit mod))- | f && moduleName mod == m- = parens (text "from" <+> ppr (moduleUnit mod))- | (pkg:_) <- res- = parens (text "from" <+> ppr (mkUnit pkg)- <> comma <+> text "reexporting" <+> ppr mod)- | f- = parens (text "defined via package flags to be"- <+> ppr mod)- | otherwise = Outputable.empty- pp_sugg (SuggestHidden m mod o) = ppr m <+> provenance o- where provenance ModHidden = Outputable.empty- provenance (ModUnusable _) = Outputable.empty- provenance (ModOrigin{ fromOrigUnit = e,- fromHiddenReexport = rhs })- | Just False <- e- = parens (text "needs flag -package-id"- <+> ppr (moduleUnit mod))- | (pkg:_) <- rhs- = parens (text "needs flag -package-id"- <+> ppr (mkUnit pkg))- | otherwise = Outputable.empty--cantFindInstalledErr :: PtrString -> PtrString -> DynFlags -> ModuleName- -> InstalledFindResult -> SDoc-cantFindInstalledErr cannot_find _ dflags mod_name find_result- = ptext cannot_find <+> quotes (ppr mod_name)- $$ more_info- where- home_unit = mkHomeUnitFromFlags dflags- unit_state = unitState dflags- build_tag = waysBuildTag (ways dflags)-- more_info- = case find_result of- InstalledNoPackage pkg- -> text "no unit id matching" <+> quotes (ppr pkg) <+>- text "was found" $$ looks_like_srcpkgid pkg-- InstalledNotFound files mb_pkg- | Just pkg <- mb_pkg, not (isHomeUnitId home_unit pkg)- -> not_found_in_package pkg files-- | null files- -> text "It is not a module in the current program, or in any known package."-- | otherwise- -> tried_these files dflags-- _ -> panic "cantFindInstalledErr"-- looks_like_srcpkgid :: UnitId -> SDoc- looks_like_srcpkgid pk- -- Unsafely coerce a unit id (i.e. an installed package component- -- identifier) into a PackageId and see if it means anything.- | (pkg:pkgs) <- searchPackageId unit_state (PackageId (unitIdFS pk))- = parens (text "This unit ID looks like the source package ID;" $$- text "the real unit ID is" <+> quotes (ftext (unitIdFS (unitId pkg))) $$- (if null pkgs then Outputable.empty- else text "and" <+> int (length pkgs) <+> text "other candidates"))- -- Todo: also check if it looks like a package name!- | otherwise = Outputable.empty-- not_found_in_package pkg files- | build_tag /= ""- = let- build = if build_tag == "p" then "profiling"- else "\"" ++ build_tag ++ "\""- in- text "Perhaps you haven't installed the " <> text build <>- text " libraries for package " <> quotes (ppr pkg) <> char '?' $$- tried_these files dflags-- | otherwise- = text "There are files missing in the " <> quotes (ppr pkg) <>- text " package," $$- text "try running 'ghc-pkg check'." $$- tried_these files dflags--tried_these :: [FilePath] -> DynFlags -> SDoc-tried_these files dflags- | null files = Outputable.empty- | verbosity dflags < 3 =- text "Use -v (or `:set -v` in ghci) " <>- text "to see a list of the files searched for."- | otherwise =- hang (text "Locations searched:") 2 $ vcat (map text files)
ghc-lib.cabal view
@@ -1,7 +1,7 @@ cabal-version: >=1.22 build-type: Simple name: ghc-lib-version: 0.20201201+version: 0.20210101 license: BSD3 license-file: LICENSE category: Development@@ -80,7 +80,7 @@ hpc == 0.6.*, exceptions == 0.10.*, parsec,- ghc-lib-parser == 0.20201201+ ghc-lib-parser == 0.20210101 build-tools: alex >= 3.1, happy >= 1.19.4 other-extensions: BangPatterns@@ -163,7 +163,7 @@ GHC.Core.InstEnv, GHC.Core.Lint, GHC.Core.Make,- GHC.Core.Map,+ GHC.Core.Map.Type, GHC.Core.Multiplicity, GHC.Core.Opt.Arity, GHC.Core.Opt.CallerCC,@@ -206,6 +206,7 @@ GHC.Data.OrdList, GHC.Data.Pair, GHC.Data.ShortText,+ GHC.Data.SizedSeq, GHC.Data.Stream, GHC.Data.StringBuffer, GHC.Data.TrieMap,@@ -214,6 +215,7 @@ GHC.Driver.CmdLine, GHC.Driver.Config, GHC.Driver.Env,+ GHC.Driver.Env.Types, GHC.Driver.Flags, GHC.Driver.Hooks, GHC.Driver.Monad,@@ -354,6 +356,7 @@ GHC.UniqueSubdir, GHC.Unit, GHC.Unit.Database,+ GHC.Unit.Env, GHC.Unit.External, GHC.Unit.Finder.Types, GHC.Unit.Home,@@ -409,8 +412,7 @@ Language.Haskell.TH.Lib.Map, Language.Haskell.TH.Ppr, Language.Haskell.TH.PprLib,- Language.Haskell.TH.Syntax,- SizedSeq+ Language.Haskell.TH.Syntax exposed-modules: Paths_ghc_lib GHC@@ -430,6 +432,7 @@ GHC.Cmm.Graph GHC.Cmm.Info GHC.Cmm.Info.Build+ GHC.Cmm.LRegSet GHC.Cmm.LayoutStack GHC.Cmm.Lexer GHC.Cmm.Lint@@ -523,6 +526,7 @@ GHC.CmmToLlvm.Mangler GHC.CmmToLlvm.Ppr GHC.CmmToLlvm.Regs+ GHC.Core.Map.Expr GHC.Core.Opt.CSE GHC.Core.Opt.CallArity GHC.Core.Opt.CprAnal@@ -617,6 +621,7 @@ GHC.Llvm.Ppr GHC.Llvm.Syntax GHC.Llvm.Types+ GHC.Parser.Utils GHC.Platform.Host GHC.Plugins GHC.Rename.Bind@@ -703,9 +708,9 @@ GHC.Tc.Plugin GHC.Tc.Solver GHC.Tc.Solver.Canonical- GHC.Tc.Solver.Flatten GHC.Tc.Solver.Interact GHC.Tc.Solver.Monad+ GHC.Tc.Solver.Rewrite GHC.Tc.TyCl GHC.Tc.TyCl.Build GHC.Tc.TyCl.Class
ghc-lib/stage0/compiler/build/primop-docs.hs-incl view
@@ -12,6 +12,10 @@ , ("negateInt#","Unary negation.\n Since the negative @Int#@ range extends one further than the\n positive range, @negateInt#@ of the most negative number is an\n identity operation. This way, @negateInt#@ is always its own inverse.") , ("addIntC#","Add signed integers reporting overflow.\n First member of result is the sum truncated to an @Int#@;\n second member is zero if the true sum fits in an @Int#@,\n nonzero if overflow occurred (the sum is either too large\n or too small to fit in an @Int#@).") , ("subIntC#","Subtract signed integers reporting overflow.\n First member of result is the difference truncated to an @Int#@;\n second member is zero if the true difference fits in an @Int#@,\n nonzero if overflow occurred (the difference is either too large\n or too small to fit in an @Int#@).")+ , ("int2Float#","Convert an @Int#@ to the corresponding @Float#@ with the same\n integral value (up to truncation due to floating-point precision). e.g.\n @int2Float# 1# == 1.0#@")+ , ("int2Double#","Convert an @Int#@ to the corresponding @Double#@ with the same\n integral value (up to truncation due to floating-point precision). e.g.\n @int2Double# 1# == 1.0##@")+ , ("word2Float#","Convert an @Word#@ to the corresponding @Float#@ with the same\n integral value (up to truncation due to floating-point precision). e.g.\n @word2Float# 1## == 1.0#@")+ , ("word2Double#","Convert an @Word#@ to the corresponding @Double#@ with the same\n integral value (up to truncation due to floating-point precision). e.g.\n @word2Double# 1## == 1.0##@") , ("uncheckedIShiftL#","Shift left. Result undefined if shift amount is not\n in the range 0 to word size - 1 inclusive.") , ("uncheckedIShiftRA#","Shift right arithmetic. Result undefined if shift amount is not\n in the range 0 to word size - 1 inclusive.") , ("uncheckedIShiftRL#","Shift right logical. Result undefined if shift amount is not\n in the range 0 to word size - 1 inclusive.")
ghc-lib/stage0/lib/ghcversion.h view
@@ -5,11 +5,10 @@ #define __GLASGOW_HASKELL__ 901 #endif #if !defined(__GLASGOW_HASKELL_FULL_VERSION__)-#define __GLASGOW_HASKELL_FULL_VERSION__ "9.1.0.20201201"+#define __GLASGOW_HASKELL_FULL_VERSION__ "9.1.20201228" #endif -#define __GLASGOW_HASKELL_PATCHLEVEL1__ 0-#define __GLASGOW_HASKELL_PATCHLEVEL2__ 20201201+#define __GLASGOW_HASKELL_PATCHLEVEL1__ 20201228 #define MIN_VERSION_GLASGOW_HASKELL(ma,mi,pl1,pl2) (\ ((ma)*100+(mi)) < __GLASGOW_HASKELL__ || \
libraries/ghci/GHCi/CreateBCO.hs view
@@ -17,7 +17,7 @@ import GHCi.ResolvedBCO import GHCi.RemoteTypes import GHCi.BreakArray-import SizedSeq+import GHC.Data.SizedSeq import System.IO (fixIO) import Control.Monad
libraries/ghci/GHCi/InfoTable.hsc view
@@ -23,6 +23,8 @@ import Data.ByteString (ByteString) import Control.Monad.Fail import qualified Data.ByteString as BS+import GHC.Platform.Host (hostPlatformArch)+import GHC.Platform.ArchOS -- NOTE: Must return a pointer acceptable for use in the header of a closure. -- If tables_next_to_code is enabled, then it must point the 'code' field.@@ -63,59 +65,9 @@ funPtrToInt :: FunPtr a -> Int funPtrToInt (FunPtr a) = I## (addr2Int## a) -data Arch = ArchSPARC- | ArchPPC- | ArchX86- | ArchX86_64- | ArchAlpha- | ArchARM- | ArchAArch64- | ArchPPC64- | ArchPPC64LE- | ArchS390X- deriving Show- mkJumpToAddr :: MonadFail m => EntryFunPtr-> m ItblCodes-mkJumpToAddr ptr = do- arch <- case mArch of- Just a -> pure a- Nothing ->- -- This code must not be called. You either need to add your- -- architecture as a distinct case to 'Arch' and 'mArch', or use- -- non-TABLES_NEXT_TO_CODE mode.- fail "mkJumpToAddr: Unknown obscure arch is not supported with TABLES_NEXT_TO_CODE"- pure $ mkJumpToAddr' arch ptr---- | 'Just' if it's a known OS, or 'Nothing' otherwise.-mArch :: Maybe Arch-mArch =-#if defined(sparc_HOST_ARCH)- Just ArchSPARC-#elif defined(powerpc_HOST_ARCH)- Just ArchPPC-#elif defined(i386_HOST_ARCH)- Just ArchX86-#elif defined(x86_64_HOST_ARCH)- Just ArchX86_64-#elif defined(alpha_HOST_ARCH)- Just ArchAlpha-#elif defined(arm_HOST_ARCH)- Just ArchARM-#elif defined(aarch64_HOST_ARCH)- Just ArchAArch64-#elif defined(powerpc64_HOST_ARCH)- Just ArchPPC64-#elif defined(powerpc64le_HOST_ARCH)- Just ArchPPC64LE-#elif defined(s390x_HOST_ARCH)- Just ArchS390X-#else- Nothing-#endif--mkJumpToAddr' :: Arch -> EntryFunPtr -> ItblCodes-mkJumpToAddr' platform a = case platform of- ArchSPARC ->+mkJumpToAddr a = case hostPlatformArch of+ ArchSPARC -> pure $ -- After some consideration, we'll try this, where -- 0x55555555 stands in for the address to jump to. -- According to includes/rts/MachRegs.h, %g3 is very@@ -137,7 +89,7 @@ 0x81C0C000, 0x01000000 ] - ArchPPC ->+ ArchPPC -> pure $ -- We'll use r12, for no particular reason. -- 0xDEADBEEF stands for the address: -- 3D80DEAD lis r12,0xDEAD@@ -152,7 +104,7 @@ 0x618C0000 .|. lo16 w32, 0x7D8903A6, 0x4E800420 ] - ArchX86 ->+ ArchX86 -> pure $ -- Let the address to jump to be 0xWWXXYYZZ. -- Generate movl $0xWWXXYYZZ,%eax ; jmp *%eax -- which is@@ -167,7 +119,7 @@ in Left insnBytes - ArchX86_64 ->+ ArchX86_64 -> pure $ -- Generates: -- jmpq *.L1(%rip) -- .align 8@@ -191,7 +143,7 @@ in Left insnBytes - ArchAlpha ->+ ArchAlpha -> pure $ let w64 = fromIntegral (funPtrToInt a) :: Word64 in Right [ 0xc3800000 -- br at, .+4 , 0xa79c000c -- ldq at, 12(at)@@ -200,7 +152,7 @@ , fromIntegral (w64 .&. 0x0000FFFF) , fromIntegral ((w64 `shiftR` 32) .&. 0x0000FFFF) ] - ArchARM { } ->+ ArchARM {} -> pure $ -- Generates Arm sequence, -- ldr r1, [pc, #0] -- bx r1@@ -214,7 +166,7 @@ , 0x11, 0xff, 0x2f, 0xe1 , byte0 w32, byte1 w32, byte2 w32, byte3 w32] - ArchAArch64 { } ->+ ArchAArch64 {} -> pure $ -- Generates: -- -- ldr x1, label@@ -230,7 +182,8 @@ , 0xd61f0020 , fromIntegral w64 , fromIntegral (w64 `shiftR` 32) ]- ArchPPC64 ->++ ArchPPC_64 ELF_V1 -> pure $ -- We use the compiler's register r12 to read the function -- descriptor and the linker's register r11 as a temporary -- register to hold the function entry point.@@ -256,7 +209,7 @@ 0xE96C0010, 0x4E800420] - ArchPPC64LE ->+ ArchPPC_64 ELF_V2 -> pure $ -- The ABI requires r12 to point to the function's entry point. -- We use the medium code model where code resides in the first -- two gigabytes, so loading a non-negative32 bit address@@ -274,7 +227,7 @@ 0x618C0000 .|. lo16 w32, 0x7D8903A6, 0x4E800420 ] - ArchS390X ->+ ArchS390X -> pure $ -- Let 0xAABBCCDDEEFFGGHH be the address to jump to. -- The following code loads the address into scratch -- register r1 and jumps to it.@@ -287,6 +240,12 @@ in Left [ 0xC0, 0x1E, byte7 w64, byte6 w64, byte5 w64, byte4 w64, 0xC0, 0x19, byte3 w64, byte2 w64, byte1 w64, byte0 w64, 0x07, 0xF1 ]++ arch ->+ -- The arch isn't supported. You either need to add your architecture as a+ -- distinct case, or use non-TABLES_NEXT_TO_CODE mode.+ fail $ "mkJumpToAddr: arch is not supported with TABLES_NEXT_TO_CODE ("+ ++ show arch ++ ")" byte0 :: (Integral w) => w -> Word8 byte0 w = fromIntegral w
libraries/ghci/GHCi/ResolvedBCO.hs view
@@ -7,7 +7,7 @@ ) where import Prelude -- See note [Why do we import Prelude here?]-import SizedSeq+import GHC.Data.SizedSeq import GHCi.RemoteTypes import GHCi.BreakArray