summaryrefslogtreecommitdiff
path: root/compiler/deSugar/PmOracle.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/deSugar/PmOracle.hs')
-rw-r--r--compiler/deSugar/PmOracle.hs190
1 files changed, 11 insertions, 179 deletions
diff --git a/compiler/deSugar/PmOracle.hs b/compiler/deSugar/PmOracle.hs
index 93c4d1d959..f9abae481c 100644
--- a/compiler/deSugar/PmOracle.hs
+++ b/compiler/deSugar/PmOracle.hs
@@ -31,7 +31,7 @@ module PmOracle (
import GhcPrelude
-import PmExpr
+import PmTypes
import DynFlags
import Outputable
@@ -77,7 +77,6 @@ import Control.Monad.Trans.State.Strict
import Data.Bifunctor (second)
import Data.Foldable (foldlM)
import Data.List (find)
-import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Semigroup as Semigroup
@@ -100,22 +99,6 @@ mkPmId ty = getUniqueM >>= \unique ->
-----------------------------------------------
-- * Caching possible matches of a COMPLETE set
-type ConLikeSet = UniqDSet ConLike
-
--- | A data type caching the results of 'completeMatchConLikes' with support for
--- deletion of contructors that were already matched on.
-data PossibleMatches
- = PM TyCon (NonEmpty ConLikeSet)
- -- ^ Each ConLikeSet is a (subset of) the constructors in a COMPLETE pragma
- -- 'NonEmpty' because the empty case would mean that the type has no COMPLETE
- -- set at all, for which we have 'NoPM'
- | NoPM
- -- ^ No COMPLETE set for this type (yet). Think of overloaded literals.
-
-instance Outputable PossibleMatches where
- ppr (PM _tc cs) = ppr (NonEmpty.toList cs)
- ppr NoPM = text "<NoPM>"
-
initIM :: Type -> DsM (Maybe PossibleMatches)
initIM ty = case splitTyConApp_maybe ty of
Nothing -> pure Nothing
@@ -235,26 +218,6 @@ equateTyVars ex_tvs1 ex_tvs2
-- * Pattern match oracle
--- | Term and type constraints to accompany each value vector abstraction.
--- For efficiency, we store the term oracle state instead of the term
--- constraints.
-data Delta = MkDelta { delta_ty_cs :: Bag EvVar -- Type oracle; things like a~Int
- , delta_tm_cs :: TmState } -- Term oracle; things like x~Nothing
-
--- | An initial delta that is always satisfiable
-initDelta :: Delta
-initDelta = MkDelta emptyBag initTmState
-
-instance Outputable Delta where
- ppr delta = vcat [
- -- intentionally formatted this way enable the dev to comment in only
- -- the info she needs
- ppr (delta_tm_cs delta),
- ppr (pprEvVarWithType <$> delta_ty_cs delta)
- --ppr (delta_ty_cs delta)
- ]
-
-
{- Note [Recovering from unsatisfiable pattern-matching constraints]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider the following code (see #12957 and #15450):
@@ -603,68 +566,10 @@ tyIsSatisfiable recheck_complete_sets new_ty_cs = SC $ \delta -> do
{- *********************************************************************
* *
- SharedIdEnv
DIdEnv with sharing
* *
********************************************************************* -}
--- | Either @Indirect x@, meaning the value is represented by that of @x@, or
--- an @Entry@ containing containing the actual value it represents.
-data Shared a
- = Indirect Id
- | Entry a
-
--- | A 'DIdEnv' in which entries can be shared by multiple 'Id's.
--- Merge equivalence classes of two Ids by 'setIndirectSDIE' and set the entry
--- of an Id with 'setEntrySDIE'.
-newtype SharedDIdEnv a
- = SDIE { unSDIE :: DIdEnv (Shared a) }
-
-emptySDIE :: SharedDIdEnv a
-emptySDIE = SDIE emptyDVarEnv
-
-lookupReprAndEntrySDIE :: SharedDIdEnv a -> Id -> (Id, Maybe a)
-lookupReprAndEntrySDIE sdie@(SDIE env) x = case lookupDVarEnv env x of
- Nothing -> (x, Nothing)
- Just (Indirect y) -> lookupReprAndEntrySDIE sdie y
- Just (Entry a) -> (x, Just a)
-
--- | @lookupSDIE env x@ looks up an entry for @x@, looking through all
--- 'Indirect's until it finds a shared 'Entry'.
-lookupSDIE :: SharedDIdEnv a -> Id -> Maybe a
-lookupSDIE sdie x = snd (lookupReprAndEntrySDIE sdie x)
-
--- | Check if two variables are part of the same equivalence class.
-sameRepresentative :: SharedDIdEnv a -> Id -> Id -> Bool
-sameRepresentative sdie x y =
- fst (lookupReprAndEntrySDIE sdie x) == fst (lookupReprAndEntrySDIE sdie y)
-
--- | @setIndirectSDIE env x y@ sets @x@'s 'Entry' to @Indirect y@, thereby
--- merging @x@'s equivalence class into @y@'s. This will discard all info on
--- @x@!
-setIndirectSDIE :: SharedDIdEnv a -> Id -> Id -> SharedDIdEnv a
-setIndirectSDIE sdie@(SDIE env) x y =
- SDIE $ extendDVarEnv env (fst (lookupReprAndEntrySDIE sdie x)) (Indirect y)
-
--- | @setEntrySDIE env x a@ sets the 'Entry' @x@ is associated with to @a@,
--- thereby modifying its whole equivalence class.
-setEntrySDIE :: SharedDIdEnv a -> Id -> a -> SharedDIdEnv a
-setEntrySDIE sdie@(SDIE env) x a =
- SDIE $ extendDVarEnv env (fst (lookupReprAndEntrySDIE sdie x)) (Entry a)
-
-traverseSharedIdEnv :: Applicative f => (a -> f b) -> SharedDIdEnv a -> f (SharedDIdEnv b)
-traverseSharedIdEnv f = fmap (SDIE . listToUDFM) . traverse g . udfmToList . unSDIE
- where
- g (u, Indirect y) = pure (u,Indirect y)
- g (u, Entry a) = (u,) . Entry <$> f a
-
-instance Outputable a => Outputable (Shared a) where
- ppr (Indirect x) = ppr x
- ppr (Entry a) = ppr a
-
-instance Outputable a => Outputable (SharedDIdEnv a) where
- ppr (SDIE env) = ppr env
-
{- *********************************************************************
* *
@@ -673,66 +578,6 @@ instance Outputable a => Outputable (SharedDIdEnv a) where
* *
********************************************************************* -}
--- | The term oracle state. Stores 'VarInfo' for encountered 'Id's. These
--- entries are possibly shared when we figure out that two variables must be
--- equal, thus represent the same set of values.
---
--- See Note [TmState invariants].
-newtype TmState = TS (SharedDIdEnv VarInfo)
- -- Deterministic so that we generate deterministic error messages
-
--- | Information about an 'Id'. Stores positive ('vi_pos') facts, like @x ~ Just 42@,
--- and negative ('vi_neg') facts, like "x is not (:)".
--- Also caches the type ('vi_ty'), the 'PossibleMatches' of a COMPLETE set
--- ('vi_cache') and the number of times each variable was refined
--- ('vi_n_refines').
---
--- Subject to Note [The Pos/Neg invariant].
-data VarInfo
- = VI
- { vi_ty :: !Type
- -- ^ The type of the variable. Important for rejecting possible GADT
- -- constructors or incompatible pattern synonyms (@Just42 :: Maybe Int@).
-
- , vi_pos :: [(PmAltCon, [Id])]
- -- ^ Positive info: 'PmExprCon's it is (i.e. @x ~ [Just y, PatSyn z]@), all
- -- at the same time (i.e. conjunctive). We need a list because of nested
- -- pattern matches involving pattern synonym
- -- case x of { Just y -> case x of PatSyn z -> ... }
- -- However, no more than one RealDataCon in the list, otherwise contradiction
- -- because of generativity.
-
- , vi_neg :: ![PmAltCon]
- -- ^ Negative info: A list of 'PmAltCon's that it cannot match.
- -- Example, assuming
- --
- -- @
- -- data T = Leaf Int | Branch T T | Node Int T
- -- @
- --
- -- then @x /~ [Leaf, Node]@ means that @x@ cannot match a @Leaf@ or @Node@,
- -- and hence can only match @Branch@. Is orthogonal to anything from 'vi_pos',
- -- in the sense that 'eqPmAltCon' returns @PossiblyOverlap@ for any pairing
- -- between 'vi_pos' and 'vi_neg'.
-
- -- See Note [Why record both positive and negative info?]
-
- , vi_cache :: !PossibleMatches
- -- ^ A cache of the associated COMPLETE sets. At any time a superset of
- -- possible constructors of each COMPLETE set. So, if it's not in here, we
- -- can't possibly match on it. Complementary to 'vi_neg'. We still need it
- -- to recognise completion of a COMPLETE set efficiently for large enums.
-
- , vi_n_refines :: !Int
- -- ^ Purely for Check performance reasons. The number of times this
- -- representative was refined ('refineToAltCon') in the Check's ConVar split.
- -- Sadly, we can't store this info in the Check module, as it's tightly coupled
- -- to the particular 'Delta' and also is per *representative*, not per
- -- syntactic variable. Note that this number does not always correspond to the
- -- length of solutions: 'addVarConCt' might add a solution without
- -- incurring the potential exponential blowup by ConVar.
- }
-
{- Note [The Pos/Neg invariant]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Invariant applying to each VarInfo: Whenever we have @(C, [y,z])@ in 'vi_pos',
@@ -830,19 +675,6 @@ The "list" option is far simpler, but incurs some overhead in representation and
warning messages (which can be alleviated by someone with enough dedication).
-}
--- | Not user-facing.
-instance Outputable TmState where
- ppr (TS state) = ppr state
-
--- | Not user-facing.
-instance Outputable VarInfo where
- ppr (VI ty pos neg cache n)
- = braces (hcat (punctuate comma [ppr ty, ppr pos, ppr neg, ppr cache, ppr n]))
-
--- | Initial state of the oracle.
-initTmState :: TmState
-initTmState = TS emptySDIE
-
-- | A 'SatisfiabilityCheck' based on new term-level constraints.
-- Returns a new 'Delta' if the new constraints are compatible with existing
-- ones.
@@ -1098,15 +930,15 @@ ensureInhabited delta vi = fmap (set_cache vi) <$> test (vi_cache vi) -- This wo
-- impossible matches.
ensureAllPossibleMatchesInhabited :: Delta -> DsM (Maybe Delta)
ensureAllPossibleMatchesInhabited delta@MkDelta{ delta_tm_cs = TS env }
- = runMaybeT (set_tm_cs_env delta <$> traverseSharedIdEnv go env)
+ = runMaybeT (set_tm_cs_env delta <$> traverseSDIE go env)
where
set_tm_cs_env delta env = delta{ delta_tm_cs = TS env }
go vi = MaybeT (ensureInhabited delta vi)
-- | @refineToAltCon delta x con arg_tys ex_tyvars@ instantiates @con@ at
-- @arg_tys@ with fresh variables (equating existentials to @ex_tyvars@).
--- It adds a new term equality equating @x@ is to the resulting 'PmExprCon' and
--- new type equalities arising from GADT matches.
+-- It adds a new term equality equating @x@ is to the resulting 'PmAltCon' app
+-- and new type equalities arising from GADT matches.
-- If successful, returns the new @delta@ and the fresh term variables, or
-- @Nothing@ otherwise.
refineToAltCon :: Delta -> Id -> PmAltCon -> [Type] -> [TyVar] -> DsM (Maybe (Delta, [Id]))
@@ -1286,19 +1118,19 @@ addVarVarCt delta@MkDelta{ delta_tm_cs = TS env } (x, y)
-- class, otherwise we might get cyclic substitutions.
-- Cf. 'extendSubstAndSolve' and
-- @testsuite/tests/pmcheck/should_compile/CyclicSubst.hs@.
- | sameRepresentative env x y = pure delta
- | otherwise = equate delta x y
+ | sameRepresentativeSDIE env x y = pure delta
+ | otherwise = equate delta x y
-- | @equate ts@(TS env) x y@ merges the equivalence classes of @x@ and @y@ by
-- adding an indirection to the environment.
-- Makes sure that the positive and negative facts of @x@ and @y@ are
-- compatible.
--- Preconditions: @not (sameRepresentative env x y)@
+-- Preconditions: @not (sameRepresentativeSDIE env x y)@
--
-- See Note [TmState invariants].
equate :: Delta -> Id -> Id -> MaybeT DsM Delta
equate delta@MkDelta{ delta_tm_cs = TS env } x y
- = ASSERT( not (sameRepresentative env x y) )
+ = ASSERT( not (sameRepresentativeSDIE env x y) )
case (lookupSDIE env x, lookupSDIE env y) of
(Nothing, _) -> pure (delta{ delta_tm_cs = TS (setIndirectSDIE env x y) })
(_, Nothing) -> pure (delta{ delta_tm_cs = TS (setIndirectSDIE env y x) })
@@ -1323,9 +1155,9 @@ equate delta@MkDelta{ delta_tm_cs = TS env } x y
-- go!
pure delta_neg
--- | @addVarConCt x alt args ts@ extends the substitution with a mapping @x: ->
--- PmExprCon alt args@ if compatible with refutable shapes of @x@ and its
--- solution, reject (@Nothing@) otherwise.
+-- | @addVarConCt x alt args ts@ extends the substitution with a solution
+-- @x :-> (alt, args)@ if compatible with refutable shapes of @x@ and its
+-- other solutions, reject (@Nothing@) otherwise.
--
-- See Note [TmState invariants].
addVarConCt :: Delta -> Id -> PmAltCon -> [Id] -> MaybeT DsM Delta