| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Stock.Internal
Description
Shared substrate for the Stock plugin: environments, the representation
EDSL, Core/dictionary builders, the variance walk, and the Solver monoid.
Synopsis
- data Variance
- data Addr
- data ConInfo = ConInfo {}
- foldBal :: (a -> a -> a) -> [a] -> a
- repData :: GenEnv -> [[Type]] -> Type
- data GenEnv = GenEnv {
- geStock :: Maybe TyCon
- geStock1 :: Maybe TyCon
- geStock2 :: Maybe TyCon
- geWitness :: Maybe Class
- geGen :: Class
- geRepTc :: TyCon
- geU1Tc :: TyCon
- geK1Tc :: TyCon
- geProdTc :: TyCon
- geProdDc :: DataCon
- geSumTc :: TyCon
- geMeta :: MetaEnv
- geGen1 :: Gen1Env
- geRTy :: Type
- geOverride :: Maybe TyCon
- geAssign :: Maybe TyCon
- geAt :: Maybe TyCon
- geKeep :: Maybe TyCon
- geArrow :: Maybe TyCon
- geWitness1 :: Maybe Class
- geWitness2 :: Maybe Class
- geOverride2 :: Maybe TyCon
- geOverride1 :: Maybe TyCon
- data MetaEnv = MetaEnv {
- meM1 :: TyCon
- meD :: Type
- meC :: Type
- meS :: Type
- meMetaData :: TyCon
- meMetaCons :: TyCon
- meMetaSel :: TyCon
- mePrefixI :: Type
- meInfixI :: TyCon
- meLeftAssoc :: Type
- meRightAssoc :: Type
- meNotAssoc :: Type
- meNoUnpack :: Type
- meSrcNoUnpack :: Type
- meSrcUnpack :: Type
- meNoStrict :: Type
- meSrcLazy :: Type
- meSrcStrict :: Type
- meDecidedLazy :: Type
- meDecidedStrict :: Type
- meDecidedUnpack :: Type
- meJustSym :: TyCon
- meNothingSym :: Type
- data Gen1Env = Gen1Env {}
- data PluginState = PluginState {}
- andE :: [CoreExpr] -> TcPluginM CoreExpr
- freshId :: Type -> String -> TcPluginM Id
- lookupTyConMaybe :: String -> String -> TcPluginM (Maybe TyCon)
- lookupMetaEnv :: TcPluginM MetaEnv
- lookupGen1Env :: TcPluginM Gen1Env
- lookupClassMaybe :: String -> String -> TcPluginM (Maybe Class)
- lookupIdMaybe :: String -> String -> TcPluginM (Maybe Id)
- repStruct :: GenEnv -> [Type] -> Type
- rec0Of :: GenEnv -> Type -> Type
- repMeta :: GenEnv -> (DataCon -> Type) -> Type -> [DataCon] -> Type
- repMetaWith :: GenEnv -> (DataCon -> Type) -> (Type -> Type) -> Type -> [(DataCon, [Type])] -> Type
- fieldTysAt :: Type -> DataCon -> [Type]
- repMetaFts :: GenEnv -> (DataCon -> Type) -> Type -> [(DataCon, [Type])] -> Type
- fixityParts :: Fixity -> (Int, FixityDirection)
- conFixityTy :: MetaEnv -> DataCon -> TcPluginM Type
- mkFixOf :: MetaEnv -> [DataCon] -> TcPluginM (DataCon -> Type)
- rep1Field :: GenEnv -> TyVar -> Type -> Maybe Type
- type Attempt = (Maybe (EvTerm, Ct), [Ct], [Ct])
- data Repr = Repr {}
- mkRepr :: Maybe TyCon -> Type -> Maybe Repr
- mkStockCo :: UnivCoProvenance -> Role -> Type -> Type -> Coercion
- reshapeCo :: Type -> Type -> Type -> Coercion
- castReshape :: CoreExpr -> Coercion -> CoreExpr
- peelOverride1 :: GenEnv -> Type -> (Type, Maybe [Type])
- peelOverride1With :: OvTcs -> Type -> (Type, Maybe [Type])
- ovTcsGen :: String -> GenEnv -> OvTcs
- data OvTcs = OvTcs {}
- lookupOvTcs :: String -> TcPluginM OvTcs
- decodeOvCfg :: OvTcs -> Type -> Type -> Maybe [Type]
- decodePositional :: Type -> Maybe [[Type]]
- promotedListElems :: Type -> Maybe [Type]
- decodeEntry :: TyCon -> TyCon -> TyCon -> Type -> Maybe (Addr, Type)
- resolveCellsRaw :: [DataCon] -> Type -> [(Addr, Type)] -> Either SDoc [((Int, Int), Type)]
- override1Mod :: GenEnv -> Maybe [Type] -> Int -> Maybe Type
- override1ModWith :: Maybe TyCon -> Maybe [Type] -> Int -> Maybe Type
- coDown1 :: GenEnv -> TyCon -> Type -> Type -> Type -> Type -> Coercion
- coDown1With :: Maybe TyCon -> TyCon -> Type -> Type -> Type -> Type -> Coercion
- peelOverride2With :: OvTcs -> Type -> (Type, Maybe [Type])
- coDown2With :: Maybe TyCon -> TyCon -> Type -> Type -> Type -> Type -> Type -> Coercion
- mkStockReprEq :: Type -> Type -> Type
- overrideFieldTypes :: GenEnv -> Type -> Maybe (Type, [(DataCon, [Type])])
- resolveCells :: [DataCon] -> Type -> [(Addr, Type)] -> Either SDoc [((Int, Int), Type)]
- modifierType :: Type -> Type -> Either SDoc Type
- mkOverrideRepr :: GenEnv -> CtLoc -> Type -> TcPluginM (Maybe (Either SDoc (Repr, [Ct])))
- buildOverride :: CtLoc -> TyCon -> TyCon -> TyCon -> TyCon -> TyCon -> TyCon -> Type -> Type -> Type -> TcPluginM (Either SDoc (Repr, [Ct]))
- dcUnpacked :: DataCon -> Bool
- buildPositional :: CtLoc -> TyCon -> TyCon -> TyCon -> Type -> Type -> Type -> [DataCon] -> [[Type]] -> TcPluginM (Either SDoc (Repr, [Ct]))
- resolveOverride :: CtLoc -> TyCon -> TyCon -> Type -> Type -> Type -> [DataCon] -> [(Addr, Type)] -> TcPluginM (Either SDoc (Repr, [Ct]))
- data Hop
- resolveAddr :: [DataCon] -> Type -> Addr -> Either SDoc [(Int, Int)]
- allCells :: [DataCon] -> Type -> [(Int, Int)]
- foldHops :: [DataCon] -> Type -> [(Int, Int)] -> [Hop] -> Either SDoc [(Int, Int)]
- labelAt :: DataCon -> Int -> Maybe String
- decodeArrow :: TyCon -> Type -> Maybe ([Type], Type)
- decodeHop :: Type -> Maybe Hop
- decodeSel :: TyCon -> Type -> Maybe Addr
- reprOverridden :: Repr -> Bool
- reprHasFields :: Repr -> Bool
- reprIsEnum :: Repr -> Bool
- reprSingleCon :: Repr -> Bool
- reprEmpty :: Repr -> Bool
- reprUnpacked :: Repr -> Bool
- mkClassDict :: Class -> Type -> [CoreExpr] -> CoreExpr
- conAppAt :: Type -> DataCon -> [CoreExpr] -> CoreExpr
- recClassDict :: Class -> Type -> (Id -> TcPluginM [CoreExpr]) -> TcPluginM CoreExpr
- recDictWith :: Class -> Type -> [CoreExpr] -> [(Int, CoreExpr)] -> TcPluginM CoreExpr
- defMethId :: Class -> Int -> TcPluginM Id
- data FieldKind
- classifyField :: TyVar -> Type -> Type -> Maybe FieldKind
- data Roles r = Roles {
- onParam :: r
- onConst :: CtEvidence -> Type -> r
- onApply :: CtEvidence -> Type -> (Type -> Coercion) -> r
- interpField :: Class -> Class -> TyVar -> Type -> CtLoc -> Maybe Type -> Roles r -> Type -> TcPluginM (Maybe (r, [Ct]))
- fieldsAt :: [Type] -> DataCon -> Type -> [Type]
- zipLift2 :: TyCon -> [Type] -> (Type -> Coercion) -> Type -> Type -> Type -> Id -> Id -> (Int -> Int -> CoreExpr) -> ([CoreExpr] -> TcPluginM CoreExpr) -> (Int -> Type -> Id -> Id -> TcPluginM (Maybe (CoreExpr, [Ct]))) -> TcPluginM (Maybe (CoreExpr, [Ct]))
- destructInner :: TyCon -> [Type] -> CoreExpr -> Id -> Type -> [CoreAlt] -> CoreExpr
- newtype Solver = Solver {}
- notImplemented :: PluginState -> Ct -> SDoc -> TcPluginM Attempt
- toDatatype :: Type -> Repr -> Datatype
- runDeriverAttempt :: Deriver -> Ct -> Class -> Datatype -> TcPluginM Attempt
- tryWitness :: PluginState -> Ct -> Class -> Datatype -> TcPluginM (Maybe Attempt)
- tryWitness1 :: PluginState -> Ct -> Class -> Type -> Type -> TcPluginM (Maybe Attempt)
- tryWitness2 :: PluginState -> Ct -> Class -> Type -> Type -> TcPluginM (Maybe Attempt)
- conPrec :: DataCon -> TcPluginM Integer
- flipV :: Variance -> Variance
- varMap :: Class -> Maybe Class -> CtLoc -> TyVar -> Type -> Maybe CoreExpr -> Maybe CoreExpr -> Variance -> Type -> TcPluginM (Maybe (CoreExpr, [Ct]))
- varMapN :: Class -> Maybe Class -> CtLoc -> [(TyVar, Type, Maybe CoreExpr, Maybe CoreExpr)] -> Maybe (Type -> TcPluginM (Maybe (CoreExpr, [Ct]))) -> Variance -> Type -> TcPluginM (Maybe (CoreExpr, [Ct]))
- freshTyVar :: String -> TcPluginM TyVar
- freshTyVarK :: Kind -> String -> TcPluginM TyVar
- unwrapEv :: EvTerm -> CoreExpr
- data ReadPrecEnv = ReadPrecEnv {}
- lookupReadPrecEnv :: CtLoc -> TcPluginM (ReadPrecEnv, Ct)
- buildReadPrecBody :: ReadPrecEnv -> Type -> (DataCon -> [Id] -> CoreExpr) -> [(DataCon, [(Type, CoreExpr)])] -> TcPluginM CoreExpr
Documentation
Synthesize an Enum dictionary for an enumeration, mirroring GHC's
derived Enum: fromEnum is the constructor tag, toEnum uses
tagToEnum#. succpredenumFromTo/enumFromThenTo come from the
class default methods (correct and bounded); enumFrom/enumFromThen are
overridden to stop at the last constructor (the defaults would run to
maxBound::Int and crash).
A decoded entry's address: a --> / := path of hops (narrowing the
(constructor, field) scope), or a type selector.
One constructor's representation: the constructor itself and its field types (instantiated at the inner type's arguments).
foldBal :: (a -> a -> a) -> [a] -> a Source #
A balanced binary fold (GHC's foldBal): splits the list in half and
recurses, giving (a `op` b) `op` (c `op` d) rather than a right-nested
chain. Precondition: non-empty.
repData :: GenEnv -> [[Type]] -> Type Source #
Rewrite Rep (Stock T) to its structural representation. The coercion is
a plugin-asserted univ coercion (there is no real Generic axiom); the
from/to we synthesize use the same assertion, so the two cohere. We only
handle single-constructor types (products) so far.
Entities looked up once for Generic synthesis: the Generic class, the
Rep family, and the representation pieces U1, K1/Rec0 and :*:.
Constructors
| GenEnv | |
Fields
| |
The M1 newtype and the promoted Meta pieces needed to build the
D1C1S1 metadata layers of a faithful (nominal) Rep.
Constructors
| MetaEnv | |
Fields
| |
Generic1 entities: the class, the Rep1 family, and the parameter-aware
representation pieces Par1/Rec1/(:.:).
data PluginState Source #
Plugin state: error-message dedup set + the Generic entities.
andE :: [CoreExpr] -> TcPluginM CoreExpr Source #
Short-circuiting conjunction of Bool-valued Core expressions — reads like
and [b0, b1, …] but builds the nested case e of { False -> False; True ->
… } chain, the same Core a derived && chain produces: no list, no
allocation, byte-identical to stock deriving.
lookupMetaEnv :: TcPluginM MetaEnv Source #
Look up the M1 + promoted Meta entities for metadata layers.
lookupGen1Env :: TcPluginM Gen1Env Source #
Look up the Generic1 / Rep1 entities.
lookupClassMaybe :: String -> String -> TcPluginM (Maybe Class) Source #
Look up a class by module + name, Nothing if its module isn't available.
lookupIdMaybe :: String -> String -> TcPluginM (Maybe Id) Source #
Look up a term-level identifier (a function/value) by module + name,
Nothing if its module isn't available — for companion derivers that need to
reference a library function (e.g. QuickCheck's oneof).
repStruct :: GenEnv -> [Type] -> Type Source #
The structural Rep type for a single constructor with the given field
types: U1 when there are no fields, otherwise a balanced :*: tree of
Rec0 field (matching GHC's foldBal nesting). No M1 metadata layers
yet — this is a valid representation that Generically can use, just not
byte-identical to stock's.
rec0Of :: GenEnv -> Type -> Type Source #
The faithful Rep with metadata layers: D1 meta (C1 meta (S1 meta Rec0
… :*: …) :+: …) — byte-identical in shape to GHC's stock Rep (balanced
:+:/:*:, M1 wrappers carrying promoted Meta). Used as the rewrite
target; the value-level from/to build the un-M1 repData value and
bridge with a representational coercion (the M1s are newtypes).
| Rec0 t = K1 R t — the field representation for a constant (and for every
field in plain Generic).
repMetaWith :: GenEnv -> (DataCon -> Type) -> (Type -> Type) -> Type -> [(DataCon, [Type])] -> Type Source #
fieldTysAt :: Type -> DataCon -> [Type] Source #
A constructor's field types, instantiated at the inner type's arguments,
so a parameterised type such as Pair Int yields [Int, Int] rather than
[a, a] (and Pair a yields the skolem [a, a]).
fixityParts :: Fixity -> (Int, FixityDirection) Source #
conFixityTy :: MetaEnv -> DataCon -> TcPluginM Type Source #
The per-constructor MetaCons fixity meta ('Infix assoc prec / 'PrefixI), precomputed (it needs the renamer's fixity environment).
mkFixOf :: MetaEnv -> [DataCon] -> TcPluginM (DataCon -> Type) Source #
A pure fixity lookup over a fixed constructor set (for repMetaWith).
rep1Field :: GenEnv -> TyVar -> Type -> Maybe Type Source #
Classify a field for Rep1: the bare parameter a ⇒ Par1; g a with
g closed ⇒ Rec1 g; a field without the parameter ⇒ Rec0 (constant).
Nothing for shapes we don't yet handle (composition f (g a), or the
parameter in a position other than the last argument of a closed functor).
type Attempt = (Maybe (EvTerm, Ct), [Ct], [Ct]) Source #
Try to solve every wanted constraint by direct synthesis. Synthesis may
emit further wanted constraints (e.g. Eq on a field type), which we hand
back to the solver alongside our solutions.
The representation of Stock Inner: the inner type, the newtype-unwrapping
coercion wrapped ~R inner, and the constructors.
mkRepr :: Maybe TyCon -> Type -> Maybe Repr Source #
Recognise Stock Inner where Stock is exactly our wrapper newtype
(identified by TyCon, not by name — so an unrelated user type called
Stock is never touched) and Inner is a concrete algebraic type, and read
off its representation. Returns Nothing for anything we don't own or can't
analyse (including when our Stock couldn't be located, i.e. ourStock is
Nothing).
mkStockCo :: UnivCoProvenance -> Role -> Type -> Type -> Coercion Source #
A plugin-asserted coercion (there is no real axiom; the plugin vouches for
the representational equality). mkUnivCo gained a [Coercion] dependency
argument in GHC 9.12, so this wrapper keeps call sites version-agnostic.
reshapeCo :: Type -> Type -> Type -> Coercion Source #
The Override(1/2) field reshape coercion h t ~R m t — Refl when the
field is not overridden (h == m), else the plugin-asserted representational
equality. Shared by every synthesizer that reshapes a functor field.
castReshape :: CoreExpr -> Coercion -> CoreExpr Source #
Cast by a reshape coercion, skipping the no-op Refl (so non-overridden
fields stay syntactically untouched and the emitted Core is byte-identical).
peelOverride1 :: GenEnv -> Type -> (Type, Maybe [Type]) Source #
Peel Override1 cfg f to the real constructor and its per-field positional
modifiers (single inner list); a non-overridden f gives (f, Nothing).
peelOverride1With :: OvTcs -> Type -> (Type, Maybe [Type]) Source #
As peelOverride1, but taking the TyCon bundle directly so callers
without a GenEnv (the companion Deriver1s) can peel Override1 too.
ovTcsGen :: String -> GenEnv -> OvTcs Source #
The bundle, from a GenEnv (for the built-in synthesizers).
decodeOvCfg :: OvTcs -> Type -> Type -> Maybe [Type] Source #
Decode an Override1/Override2 config to the (first) constructor's
per-field raw modifiers (Keep where a field is unaddressed). Both the
positional '[ '[m, _, …] ] form AND the field-keyed entry list '[ "x" ':=
m, 'C '--> 0 '--> m, … ] work — the same surface as value Override, only
the modifier kind differs (a functor here). modifierType is not applied:
the synthesizers receive m and reshape h a to m a themselves.
decodePositional :: Type -> Maybe [[Type]] Source #
A positional config '[ '[m00, m01, …], … ] as per-constructor,
per-field modifier lists, or Nothing if cfg is not a concrete
list-of-lists (in which case the entry-list decoder is tried instead).
promotedListElems :: Type -> Maybe [Type] Source #
A balanced list of the elements of a promoted type-level list
('[a, b, …]), or Nothing if ty is not a concrete promoted list.
decodeEntry :: TyCon -> TyCon -> TyCon -> Type -> Maybe (Addr, Type) Source #
Decode one config entry into its address and modifier. Three surfaces:
a --> path ('P --> 0 --> m), a := entry ("x" := m or At C n := m),
or — still through := — a type selector (Int := m). Robust to leading
invisible kind arguments (the visible operands are the last two).
resolveCellsRaw :: [DataCon] -> Type -> [(Addr, Type)] -> Either SDoc [((Int, Int), Type)] Source #
As resolveCells, but keeping the raw modifier m per cell (not
modifierType-applied) — for Override1/Override2, whose synthesizers
want the bare functor modifier (they reshape h a to m a themselves).
override1Mod :: GenEnv -> Maybe [Type] -> Int -> Maybe Type Source #
The modifier functor for field i under an Override1 config, if any (and
not Keep): the field's h a is then reshaped to m a.
override1ModWith :: Maybe TyCon -> Maybe [Type] -> Int -> Maybe Type Source #
As override1Mod, but taking the Keep TyCon directly (for Deriver1s).
coDown1 :: GenEnv -> TyCon -> Type -> Type -> Type -> Type -> Coercion Source #
Stock1 (Override1 cfg realF) t ~R realF t — two newtype hops (one when
there is no Override1 wrapper).
peelOverride2With :: OvTcs -> Type -> (Type, Maybe [Type]) Source #
The Stock2 counterpart of peelOverride1With: peel Override2 cfg realP
to the real constructor and its per-field positional modifiers (for Deriver2s).
coDown2With :: Maybe TyCon -> TyCon -> Type -> Type -> Type -> Type -> Type -> Coercion Source #
Stock2 (Override2 cfg realP) t1 t2 ~R realP t1 t2 — two newtype hops (one
when there is no Override2 wrapper). For Deriver2s.
mkStockReprEq :: Type -> Type -> Type Source #
Recognise Stock (Override T cfg) and build the override representation of
T. The unwrap coercion chains through both newtypes; fields named in
cfg take their modifier type, with a per-cell realτ ~R modτ coercion
emitted as a wanted (so GHC validates the override and reports a clean error
if it isn't coercible); unnamed fields are unchanged. Nothing if this is
not an Override; Left if it is but malformed. v1: single-constructor,
keyed by record-field name, modifiers saturated (Type, pin) or unary
(Type -> Type, broadcast).
| Representational primitive equality a ~R# b — the wanted whose evidence
coercion we splice per overridden cell. (Renamed in GHC 9.14.)
overrideFieldTypes :: GenEnv -> Type -> Maybe (Type, [(DataCon, [Type])]) Source #
Pure decode of Stock (Override T cfg) to T and its constructors paired
with their per-field modifier types (Keep or an unmatched cell ⇒ the real
field type). The Generic Rep rewriter (rewriteRep) needs
only these types; the value-level coercion wanteds are emitted by the solver
(synthGeneric via mkOverrideRepr), and both compute identical modifier
types (same modifierType) so the Rep and from/to cohere. Nothing
if arg is not a Stock (Override …) (the caller falls back to mkRepr).
resolveCells :: [DataCon] -> Type -> [(Addr, Type)] -> Either SDoc [((Int, Int), Type)] Source #
Resolve every entry to its cells (with kind-dispatched modifier types), left to right, enforcing the no-overlap law against the cells already claimed.
modifierType :: Type -> Type -> Either SDoc Type Source #
Kind-dispatch a modifier: a saturated Type pins the field to that type;
a unary Type -> Type is applied to the field's own type (broadcast).
buildOverride :: CtLoc -> TyCon -> TyCon -> TyCon -> TyCon -> TyCon -> TyCon -> Type -> Type -> Type -> TcPluginM (Either SDoc (Repr, [Ct])) Source #
The body of mkOverrideRepr, once it is known to be an Override.
Two config shapes (see docs/override-design.md): a positional
list-of-lists '[ '[m, …], … ] (one inner list per constructor, one element
per field, Keep = no change), or an entry list '[ sel ':= m, 'C --> n
--> m, … ] — both multi-constructor, selector- and path-addressed.
dcUnpacked :: DataCon -> Bool Source #
True if a constructor's runtime arg representation differs from its source
arg types (UNPACK, -funbox-small-strict-fields, existentials, …).
buildPositional :: CtLoc -> TyCon -> TyCon -> TyCon -> Type -> Type -> Type -> [DataCon] -> [[Type]] -> TcPluginM (Either SDoc (Repr, [Ct])) Source #
Build the Repr for a positional config: each constructor's inner list
gives a modifier per field — Keep leaves the field, any other type m
replaces it (kind-dispatched pin vs broadcast by modifierType), with a
per-cell realτ ~R modτ coercion emitted as a wanted.
resolveOverride :: CtLoc -> TyCon -> TyCon -> Type -> Type -> Type -> [DataCon] -> [(Addr, Type)] -> TcPluginM (Either SDoc (Repr, [Ct])) Source #
Resolve decoded (addr, modifier) entries against all the type's
constructors: turn each address into its cell set (ctorIndex, fieldIndex),
reject any cell claimed twice, kind-dispatch each modifier per cell, emit the
per-cell coercion wanteds, and assemble the (multi-constructor) Repr.
A path hop (design §4): a constructor, a field by position, or a field by
label. Constructor hops match by occ-name, so both 'P and (for a
single-constructor type) the bare type name resolve.
Constructors
| HopCon FastString | |
| HopPos Integer | |
| HopLabel FastString |
resolveAddr :: [DataCon] -> Type -> Addr -> Either SDoc [(Int, Int)] Source #
Resolve one address to its (ctorIndex, fieldIndex) cell set.
allCells :: [DataCon] -> Type -> [(Int, Int)] Source #
Every (ctorIndex, fieldIndex) cell of the type. Uses the source arity
(not fieldTysAt) so it is safe when targetTy is an unsaturated j -> Type
(the Override1/Override2 case).
foldHops :: [DataCon] -> Type -> [(Int, Int)] -> [Hop] -> Either SDoc [(Int, Int)] Source #
Narrow the cell scope by each hop in turn.
labelAt :: DataCon -> Int -> Maybe String Source #
The record label of a constructor's i-th field, if it has one.
decodeArrow :: TyCon -> Type -> Maybe ([Type], Type) Source #
Flatten a right-nested a --> b --> … --> m into its hop types and the
terminal modifier; Nothing if e is not a --> application.
decodeHop :: Type -> Maybe Hop Source #
Classify a path hop by kind: Symbol ⇒ label, Nat ⇒ position, otherwise
a (promoted constructor / type) matched later by occ-name.
decodeSel :: TyCon -> Type -> Maybe Addr Source #
Classify the left of :=: a Symbol is a label path, At C n a
constructor+position path, anything else a type selector.
reprOverridden :: Repr -> Bool Source #
Does any cell carry a non-trivial override (a modifier coercion that isn't
reflexivity)? The raw viaSynth synthesizers (Ord/Show/Read/Enum/Ix)
recompute field types from the constructor and so cannot honour an override;
the dispatcher uses this to reject them loudly rather than silently ignore it.
reprHasFields :: Repr -> Bool Source #
reprIsEnum :: Repr -> Bool Source #
reprSingleCon :: Repr -> Bool Source #
reprUnpacked :: Repr -> Bool Source #
Does any constructor have fields whose runtime representation differs from
their source types? This happens with UNPACK / -funbox-small-strict-fields
(a strict !Int becomes Int#) and with existentials/GADTs. We match on the
source types, so such constructors would yield ill-typed Core — we refuse them.
mkClassDict :: Class -> Type -> [CoreExpr] -> CoreExpr Source #
Apply a class's dictionary constructor: C:Cls @ty m1 .. mn.
conAppAt :: Type -> DataCon -> [CoreExpr] -> CoreExpr Source #
Apply a constructor, supplying the inner type's type arguments first
(e.g. Pair @Int e1 e2), so it works for parameterised types.
recClassDict :: Class -> Type -> (Id -> TcPluginM [CoreExpr]) -> TcPluginM CoreExpr Source #
Build a (possibly self-referential) dictionary: let rec d = C:Cls ty (mk d)
in d. The callback receives the dictionary binder so fields can refer back
to it (e.g. to use class default methods).
recDictWith :: Class -> Type -> [CoreExpr] -> [(Int, CoreExpr)] -> TcPluginM CoreExpr Source #
Build a recursive dictionary giving explicit superclass dicts and explicit
implementations for the listed method indices; every other method comes from
the class's own default method (applied to the recursive dictionary). This
is how we fill many-method classes (Foldable) from a single key method.
defMethId :: Class -> Int -> TcPluginM Id Source #
The default-method Id for the i-th method of a class (for filling dictionary fields we don't override, via a recursive dictionary).
How a constructor field relates to the functor parameter a.
How to use one constructor field, by its relationship to the parameter.
This is the single place that distinguishes a lifted class (Eq1/Ord1/
Show1/Read1) from its twin: the onParam leaf is what changes (the
supplied function vs the field's own instance). onConst/onApply receive
the wanted-evidence the field needs.
Constructors
| Roles | |
Fields
| |
Arguments
| :: Class | the constant-field class ( |
| -> Class | the lifted class ( |
| -> TyVar | |
| -> Type | |
| -> CtLoc | |
| -> Maybe Type |
|
| -> Roles r | |
| -> Type | |
| -> TcPluginM (Maybe (r, [Ct])) |
Classify a field and pick the matching role, emitting the wanted that role
needs (a C H for a constant, the lifted C1 H for an H a field). Under an
Override1 the H a field is reshaped to m a: the wanted is the lifted C1
m and onApply receives m plus the h t ~R m t coercion builder.
Nothing if the field shape is unsupported (e.g. contravariant, nested).
fieldsAt :: [Type] -> DataCon -> Type -> [Type] Source #
The field types of a constructor with the Stock1 parameter set to ty.
zipLift2 :: TyCon -> [Type] -> (Type -> Coercion) -> Type -> Type -> Type -> Id -> Id -> (Int -> Int -> CoreExpr) -> ([CoreExpr] -> TcPluginM CoreExpr) -> (Int -> Type -> Id -> Id -> TcPluginM (Maybe (CoreExpr, [Ct]))) -> TcPluginM (Maybe (CoreExpr, [Ct])) Source #
The two-scrutinee SOP walk — the Stock1 counterpart to matchSOP
(which is single-scrutinee, in Stock.Derive). Walk two values of the same
Stock1 F shape in lock-step: matching constructors combine their per-field
results, mismatched constructors give a fixed answer. This is the skeleton
shared by liftEq (combine = short-circuit &&, mismatch = False) and
liftCompare (combine = lexicographic, mismatch = tag order). fieldOp
produces one field-pair's result (via interpField); combine folds a
constructor's field results.
destructInner :: TyCon -> [Type] -> CoreExpr -> Id -> Type -> [CoreAlt] -> CoreExpr Source #
Destructure a scrutinee of inner type F instTys (already coerced to
F instTys) into per-constructor alternatives. A data type becomes a real
Case; a newtype has no runtime constructor — its single "constructor" is
a zero-cost coercion — so we unwrap the one field with a cast instead (a
DataAlt on a newtype is rejected by Core Lint).
Solve C (Stock Inner) by building the dictionary from Inner's
constructors. We only act on the Stock newtype, so unrelated code is
never affected. Eq handles any single-level algebraic type; Ord is
limited to enumerations; anything else gets a clear "not implemented" error.
| A solver for one wrapper: Just the Attempt if it owns the wrapper (even
an error it reports), or Nothing to defer to the next. The Monoid is
first-success, so dispatch is a composition stockSolver <> … — and a
companion solver would be just one more element.
The first-success Monoid is exactly Alt (MaybeT m) (the Alternative-as-
Monoid that stops at the first solver returning a result), under the reader
arrows — so we derive it rather than hand-write it.
Constructors
| Solver | |
notImplemented :: PluginState -> Ct -> SDoc -> TcPluginM Attempt Source #
toDatatype :: Type -> Repr -> Datatype Source #
Build compare :: wrapped -> wrapped -> Ordering for any single-level
algebraic type, matching derived Ord: compare constructor tags first, and
for the same constructor compare the fields lexicographically. Field
comparisons use each field type's own Ord (requested as wanted
constraints); the wanteds are returned alongside the expression.
runDeriverAttempt :: Deriver -> Ct -> Class -> Datatype -> TcPluginM Attempt Source #
Run a Deriver (built-in or discovered) as a solve attempt.
tryWitness :: PluginState -> Ct -> Class -> Datatype -> TcPluginM (Maybe Attempt) Source #
Discovery + dynamic loading (the extension mechanism): if a companion
package provides instance DeriveStock C, find it in the instance
environment, load its Deriver value with GHC's plugin loader, and run it —
so a new class becomes derivable via Stock just by depending on the
companion, with no change to the user's -fplugin line.
tryWitness1 :: PluginState -> Ct -> Class -> Type -> Type -> TcPluginM (Maybe Attempt) Source #
The Stock1 counterpart of tryWitness: discover a companion
instance DeriveStock1 C, load its Deriver1, and run it on the inner
type constructor f. (deriving C via Stock1 F for a lifted C.)
tryWitness2 :: PluginState -> Ct -> Class -> Type -> Type -> TcPluginM (Maybe Attempt) Source #
The Stock2 counterpart of tryWitness1: discover instance DeriveStock2
C and run its Deriver2 on the inner two-parameter constructor p.
conPrec :: DataCon -> TcPluginM Integer Source #
Eq, re-expressed through the public SDK (Datatype / Synth / field)
rather than the bespoke synthEq — a proof that the extension interface is
expressive enough to host a real, field-recursive synthesizer. Produces the
same Core as synthEq.
varMap :: Class -> Maybe Class -> CtLoc -> TyVar -> Type -> Maybe CoreExpr -> Maybe CoreExpr -> Variance -> Type -> TcPluginM (Maybe (CoreExpr, [Ct])) Source #
Build a variance-correct mapper for a field type t between t[pv:=src]
and t[pv:=tgt] (where src/tgt are the actual a/b types). This is
GHC's DeriveFunctor algorithm: recurse through function arrows flipping
variance, and through covariant functor (or contravariant) applications.
Cov tyieldst[src] -> t[tgt];Con tyieldst[tgt] -> t[src].- the bare parameter maps via
covFwd(resp.conFwd); the unavailable direction isNothing, so a parameter in the wrong position fails cleanly (e.g. a bareain a negative position is not aFunctor). fmapClssuppliesfmapfor covariant subfields;mContraCls, if given, suppliescontramapfor contravariant subfields.
varMapN :: Class -> Maybe Class -> CtLoc -> [(TyVar, Type, Maybe CoreExpr, Maybe CoreExpr)] -> Maybe (Type -> TcPluginM (Maybe (CoreExpr, [Ct]))) -> Variance -> Type -> TcPluginM (Maybe (CoreExpr, [Ct])) Source #
The n-ary variance engine behind varMap (and so behind Functor,
Contravariant, Bifunctor, Profunctor, Invariant, …, which are this
one recursion at different variance vectors). Each parameter carries its
own detection tyvar (the source instantiation it appears as in the field),
its target type, and the two directional mappers — covFwd for a covariant
occurrence (a src -> tgt), conFwd for a contravariant one (a tgt ->
src); the unavailable direction is Nothing, so a parameter used against
its declared variance fails cleanly. A covariant slot populates covFwd
only, a contravariant slot conFwd only, an invariant slot both. The
recursion is GHC's DeriveFunctor algorithm (arrows flip variance,
last-argument functor/contravariant applications recurse), now substituting
all parameters at once.
freshTyVar :: String -> TcPluginM TyVar Source #
Synthesize Functor (Stock1 F) — the covariant instance of the shared
synthMap1 engine.
data ReadPrecEnv Source #
Every combinator GHC's derived readPrec uses, looked up once.
Constructors
| ReadPrecEnv | |
lookupReadPrecEnv :: CtLoc -> TcPluginM (ReadPrecEnv, Ct) Source #
Look up the ReadPrec combinators and request a Monad ReadPrec wanted
(returned as the second component, to be emitted alongside the synthesized
instance's other wanteds).
buildReadPrecBody :: ReadPrecEnv -> Type -> (DataCon -> [Id] -> CoreExpr) -> [(DataCon, [(Type, CoreExpr)])] -> TcPluginM CoreExpr Source #
Assemble a readPrec-shaped body for element type gTy. Each constructor
carries one raw field reader (a ReadPrec ft) per field; this wraps them
exactly as GHC: nullary cons grouped into one leading choose, then prefix
(prec 10 + step) / infix (prec fixity + step) / record (prec 11 +
readField name (reset _)) cons in declaration order, all under parens.
mkConVal dc binders builds the (already wrapped/cast) constructor value.