ghc-lib-parser-9.14.1.20251220: The GHC API, decoupled from GHC versions

Safe Haskell | Ignore
Language | GHC2021

GHC.Core.Unify

Synopsis

- tcMatchTy :: HasDebugCallStack => Type -> Type -> Maybe Subst
- tcMatchTyKi :: HasDebugCallStack => Type -> Type -> Maybe Subst
- tcMatchTys :: HasDebugCallStack => [Type] -> [Type] -> Maybe Subst
- tcMatchTyKis :: HasDebugCallStack => [Type] -> [Type] -> Maybe Subst
- tcMatchTyX :: HasDebugCallStack => Subst -> Type -> Type -> Maybe Subst
- tcMatchTysX :: HasDebugCallStack => Subst -> [Type] -> [Type] -> Maybe Subst
- tcMatchTyKisX :: HasDebugCallStack => Subst -> [Type] -> [Type] -> Maybe Subst
- tcMatchTyX_BM :: HasDebugCallStack => BindTvFun -> Subst -> Type -> Type -> Maybe Subst
- ruleMatchTyKiX :: TyCoVarSet -> RnEnv2 -> TvSubstEnv -> Type -> Type -> Maybe TvSubstEnv
- tcUnifyTy :: Type -> Type -> Maybe Subst
- tcUnifyTys :: BindTvFun -> [Type] -> [Type] -> Maybe Subst
- tcUnifyFunDeps :: TyCoVarSet -> [Type] -> [Type] -> Maybe Subst
- tcUnifyDebugger :: Type -> Type -> Maybe Subst
- tcUnifyTysFG :: BindFamFun -> BindTvFun -> [Type] -> [Type] -> UnifyResult
- tcUnifyTyForInjectivity :: AmIUnifying -> InScopeSet -> Type -> Type -> Maybe Subst
- type BindTvFun = TyCoVar -> Type -> BindFlag
- type BindFamFun = TyCon -> [Type] -> Type -> BindFlag
- data BindFlag
  - = BindMe
  - | DontBindMe
- matchBindTv :: TyCoVarSet -> BindTvFun
- alwaysBindTv :: BindTvFun
- alwaysBindFam :: BindFamFun
- dontCareBindFam :: HasCallStack => BindFamFun
- type UnifyResult = UnifyResultM Subst
- data UnifyResultM a
  - = Unifiable a
  - | MaybeApart MaybeApartReason a
  - | SurelyApart
- data MaybeApartReason
  - = MARTypeFamily
  - | MARInfinite
  - | MARTypeVsConstraint
  - | MARCast
- typesCantMatch :: [(Type, Type)] -> Bool
- typesAreApart :: Type -> Type -> Bool
- liftCoMatch :: TyCoVarSet -> Type -> Coercion -> Maybe LiftingContext

# Documentation

tcMatchTy :: HasDebugCallStack => Type -> Type -> Maybe Subst #

`tcMatchTy t1 t2` produces a substitution (over fvs(t1)) `s` such that `s(t1)` equals `t2`. The returned substitution might bind coercion variables, if the variable is an argument to a GADT constructor.

Precondition: typeKind ty1 `eqType` typeKind ty2

We don't pass in a set of "template variables" to be bound by the match, because tcMatchTy (and similar functions) are always used on top-level types, so we can bind any of the free variables of the LHS. See also Note [tcMatchTy vs tcMatchTyKi]

tcMatchTyKi :: HasDebugCallStack => Type -> Type -> Maybe Subst #

Like `tcMatchTy`, but allows the kinds of the types to differ, and thus matches them as well. See also Note [tcMatchTy vs tcMatchTyKi]

tcMatchTys #

Arguments

:: HasDebugCallStack |
=> [Type] | Template
-> [Type] | Target
-> Maybe Subst | One-shot; in principle the template variables could be free in the target See (CU6) in Note [The Core unifier]

Like `tcMatchTy` but over a list of types. See also Note [tcMatchTy vs tcMatchTyKi]

tcMatchTyKis #

Arguments

:: HasDebugCallStack |
=> [Type] | Template
-> [Type] | Target
-> Maybe Subst | One-shot substitution See (CU6) in Note [The Core unifier]

Like `tcMatchTyKi` but over a list of types. See also Note [tcMatchTy vs tcMatchTyKi]

tcMatchTyX #

Arguments

:: HasDebugCallStack |
=> Subst | Substitution to extend
-> Type | Template
-> Type | Target
-> Maybe Subst |

This is similar to `tcMatchTy`, but extends a substitution See also Note [tcMatchTy vs tcMatchTyKi]

tcMatchTysX #

Arguments

:: HasDebugCallStack |
=> Subst | Substitution to extend
-> [Type] | Template
-> [Type] | Target
-> Maybe Subst | One-shot substitution

Like `tcMatchTys`, but extending a substitution See also Note [tcMatchTy vs tcMatchTyKi]

tcMatchTyKisX #

Arguments

:: HasDebugCallStack |
=> Subst | Substitution to extend
-> [Type] | Template
-> [Type] | Target
-> Maybe Subst | One-shot substitution

Like `tcMatchTyKis`, but extending a substitution See also Note [tcMatchTy vs tcMatchTyKi]

tcMatchTyX_BM :: HasDebugCallStack => BindTvFun -> Subst -> Type -> Type -> Maybe Subst #

ruleMatchTyKiX #

Arguments

:: TyCoVarSet | template variables
-> RnEnv2 |
-> TvSubstEnv | type substitution to extend
-> Type | Template
-> Type | Target
-> Maybe TvSubstEnv |

This one is called from the expression matcher, which already has a MatchEnv in hand

tcUnifyTy :: Type -> Type -> Maybe Subst #

Simple unification of two types; all type variables are bindable Precondition: the kinds are already equal

tcUnifyTys #

Arguments

:: BindTvFun |
-> [Type] |
-> [Type] |
-> Maybe Subst | A regular one-shot (idempotent) substitution that unifies the erased types. See comments for `tcUnifyTysFG`

tcUnifyFunDeps :: TyCoVarSet -> [Type] -> [Type] -> Maybe Subst #

Like `tcUnifyTys` but also unifies the kinds

tcUnifyDebugger :: Type -> Type -> Maybe Subst #

tcUnifyTysFG :: BindFamFun -> BindTvFun -> [Type] -> [Type] -> UnifyResult #

(tcUnifyTysFG bind_fam bind_tv tys1 tys2) does "fine-grain" unification of tys1 and tys2, under the control of `bind_fam` and `bind_tv`. This version requires that the kinds of the types are the same, if you unify left-to-right. See Note [The Core unifier]

tcUnifyTyForInjectivity #

Arguments

:: AmIUnifying | True = do two-way unification; False = do one-way matching. See end of sec 5.2 from the paper
-> InScopeSet |
-> Type |
-> Type |
-> Maybe Subst |

Unify or match a type-family RHS with a type (possibly another type-family RHS) Precondition: kinds are the same

type BindTvFun = TyCoVar -> Type -> BindFlag #

Some unification functions are parameterised by a `BindTvFun`, which says whether or not to allow a certain unification to take place. A `BindTvFun` takes the `TyVar` involved along with the `Type` it will potentially be bound to.

It is possible for the variable to actually be a coercion variable (Note [Matching coercion variables]), but only when one-way matching. In this case, the `Type` will be a `CoercionTy`.

type BindFamFun = TyCon -> [Type] -> Type -> BindFlag #

BindFamFun is similiar to BindTvFun, but deals with a saturated type-family application. See Note [Apartness and type families].

data BindFlag #

Constructors

BindMe | A bindable type variable
DontBindMe | Do not bind this type variable is apart See also Note [Super skolems: binding when looking up instances] in GHC.Core.InstEnv.

#### Instances

Instances details

Eq BindFlag # |
Instance details Defined in GHC.Core.Unify Methods (==) :: BindFlag -> BindFlag -> Bool # (/=) :: BindFlag -> BindFlag -> Bool #

matchBindTv :: TyCoVarSet -> BindTvFun #

Allow binding only for any variable in the set. Variables may be bound to any type. Used when doing simple matching; e.g. can we find a substitution

    S = [a :-> t1, b :-> t2] such that
        S( Maybe (a, b->Int )  =   Maybe (Bool, Char -> Int)

alwaysBindTv :: BindTvFun #

Allow the binding of any variable to any type

alwaysBindFam :: BindFamFun #

Allow the binding of a type-family application to any type

dontCareBindFam :: HasCallStack => BindFamFun #

type UnifyResult = UnifyResultM Subst #

data UnifyResultM a #

See Note [Unification result]

Constructors

Unifiable a |
MaybeApart MaybeApartReason a |
SurelyApart |

#### Instances

Instances details

Applicative UnifyResultM # |
Instance details Defined in GHC.Core.Unify Methods pure :: a -> UnifyResultM a # (<*>) :: UnifyResultM (a -> b) -> UnifyResultM a -> UnifyResultM b # liftA2 :: (a -> b -> c) -> UnifyResultM a -> UnifyResultM b -> UnifyResultM c # (*>) :: UnifyResultM a -> UnifyResultM b -> UnifyResultM b # (<*) :: UnifyResultM a -> UnifyResultM b -> UnifyResultM a #
Functor UnifyResultM # |
Instance details Defined in GHC.Core.Unify Methods fmap :: (a -> b) -> UnifyResultM a -> UnifyResultM b # (<$) :: a -> UnifyResultM b -> UnifyResultM a #
Monad UnifyResultM # |
Instance details Defined in GHC.Core.Unify Methods (>>=) :: UnifyResultM a -> (a -> UnifyResultM b) -> UnifyResultM b # (>>) :: UnifyResultM a -> UnifyResultM b -> UnifyResultM b # return :: a -> UnifyResultM a #
Outputable a => Outputable (UnifyResultM a) # |
Instance details Defined in GHC.Core.Unify Methods ppr :: UnifyResultM a -> SDoc #

data MaybeApartReason #

Why are two types `MaybeApart`? `MARInfinite` takes precedence: This is used (only) in Note [Infinitary substitution in lookup] in GHC.Core.InstEnv As of Feb 2022, we never differentiate between MARTypeFamily and MARTypeVsConstraint; it's really only MARInfinite that's interesting here.

Constructors

MARTypeFamily | matching e.g. F Int ~? Bool
MARInfinite | matching e.g. a ~? Maybe a
MARTypeVsConstraint | matching Type ~? Constraint or the arrow types See Note [Type and Constraint are not apart] in GHC.Builtin.Types.Prim
MARCast | Very obscure. See (KCU2) in Note [Kind coercions in Unify]

#### Instances

Instances details

Semigroup MaybeApartReason # |
Instance details Defined in GHC.Core.Unify Methods (<>) :: MaybeApartReason -> MaybeApartReason -> MaybeApartReason # sconcat :: NonEmpty MaybeApartReason -> MaybeApartReason # stimes :: Integral b => b -> MaybeApartReason -> MaybeApartReason #
Outputable MaybeApartReason # |
Instance details Defined in GHC.Core.Unify Methods ppr :: MaybeApartReason -> SDoc #

typesCantMatch :: [(Type, Type)] -> Bool #

Given a list of pairs of types, are any two members of a pair surely apart, even after arbitrary type function evaluation and substitution?

typesAreApart :: Type -> Type -> Bool #

liftCoMatch :: TyCoVarSet -> Type -> Coercion -> Maybe LiftingContext #

`liftCoMatch` is sort of inverse to `liftCoSubst`. In particular, if `liftCoMatch vars ty co == Just s`, then `liftCoSubst s ty == co`, where `==` there means that the result of `liftCoSubst` has the same type as the original co; but may be different under the hood. That is, it matches a type against a coercion of the same "shape", and returns a lifting substitution which could have been used to produce the given coercion from the given type. Note that this function is incomplete -- it might return Nothing when there does indeed exist a possible lifting context.

This function is incomplete in that it doesn't respect the equality in `eqType`. That is, it's possible that this will succeed for t1 and fail for t2, even when t1 `eqType` t2. That's because it depends on there being a very similar structure between the type and the coercion. This incompleteness shouldn't be all that surprising, especially because it depends on the structure of the coercion, which is a silly thing to do.

The lifting context produced doesn't have to be exacting in the roles of the mappings. This is because any use of the lifting context will also require a desired role. Thus, this algorithm prefers mapping to nominal coercions where it can do so.