stock-0.1.0.0: Stock-style deriving via coercion, with no Generic
Safe HaskellNone
LanguageGHC2021

Stock.Internal

Description

Shared substrate for the Stock plugin: environments, the representation EDSL, Core/dictionary builders, the variance walk, and the Solver monoid.

Synopsis

Documentation

data Variance Source #

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).

Constructors

Cov 
Con 

data Addr Source #

A decoded entry's address: a --> / := path of hops (narrowing the (constructor, field) scope), or a type selector.

Constructors

AddrPath [Hop] 
AddrType Type 

data ConInfo Source #

One constructor's representation: the constructor itself and its field types (instantiated at the inner type's arguments).

Constructors

ConInfo 

Fields

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.

data GenEnv Source #

Entities looked up once for Generic synthesis: the Generic class, the Rep family, and the representation pieces U1, K1/Rec0 and :*:.

Constructors

GenEnv 

Fields

data MetaEnv Source #

The M1 newtype and the promoted Meta pieces needed to build the D1C1S1 metadata layers of a faithful (nominal) Rep.

Constructors

MetaEnv 

Fields

data Gen1Env Source #

Generic1 entities: the class, the Rep1 family, and the parameter-aware representation pieces Par1/Rec1/(:.:).

Constructors

Gen1Env 

Fields

data PluginState Source #

Plugin state: error-message dedup set + the Generic entities.

Constructors

PluginState 

Fields

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.

freshId :: Type -> String -> TcPluginM Id Source #

A fresh local binder of the given type.

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 #

repMeta generalised over the per-field leaf representation: Generic uses Rec0; Generic1 uses Par1/Rec1/(:.:) (rep1Field). Each constructor comes with the field types its leaves should carry.

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]).

repMetaFts :: GenEnv -> (DataCon -> Type) -> Type -> [(DataCon, [Type])] -> Type Source #

repMeta with explicit per-constructor field types — the Generic leaves carry these (the modifier types under an Override, the real types otherwise). Pairs with the from/to that Generic builds.

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 aPar1; 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.

data Repr Source #

The representation of Stock Inner: the inner type, the newtype-unwrapping coercion wrapped ~R inner, and the constructors.

Constructors

Repr 

Fields

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 tRefl 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).

data OvTcs Source #

The Override-config TyCons a config decoder needs. Bundled so the satellite Deriver1/Deriver2s (which have no GenEnv) can pass them.

Constructors

OvTcs 

Fields

lookupOvTcs :: String -> TcPluginM OvTcs Source #

The bundle, looked up by name (for the satellite Deriver1/Deriver2s).

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).

coDown1With :: Maybe TyCon -> TyCon -> Type -> Type -> Type -> Type -> Coercion Source #

As coDown1, but taking the Override1 TyCon directly (for Deriver1s).

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.

data Hop Source #

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.

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.

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).

data FieldKind Source #

How a constructor field relates to the functor parameter a.

Constructors

FParam 
FConst 
FApp Type

is a no a H a (covariant)

data Roles r Source #

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

  • onParam :: r

    the field is the parameter a

  • onConst :: CtEvidence -> Type -> r

    a constant field (own instance) | an H a field (lifted instance of the effective H): the evidence, the effective functor (the Override1 modifier m when present, else the real h), and a coercion builder \t -> (h t ~R m t) (Refl when not overridden) so the caller can cast field values h t to/from m t.

  • onApply :: CtEvidence -> Type -> (Type -> Coercion) -> r
     

interpField Source #

Arguments

:: Class

the constant-field class (Eq/Ord/Show/Read)

-> Class

the lifted class (Eq1/Ord1/Show1/Read1)

-> TyVar 
-> Type 
-> CtLoc 
-> Maybe Type

Override1 modifier for this field, if any

-> 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).

newtype Solver Source #

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 

Instances

Instances details
Monoid Solver Source # 
Instance details

Defined in Stock.Internal

Semigroup Solver Source # 
Instance details

Defined in Stock.Internal

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 t yields t[src] -> t[tgt]; Con t yields t[tgt] -> t[src].
  • the bare parameter maps via covFwd (resp. conFwd); the unavailable direction is Nothing, so a parameter in the wrong position fails cleanly (e.g. a bare a in a negative position is not a Functor).
  • fmapCls supplies fmap for covariant subfields; mContraCls, if given, supplies contramap for 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.

freshTyVarK :: Kind -> String -> TcPluginM TyVar Source #

A fresh type variable of the given kind.

unwrapEv :: EvTerm -> CoreExpr Source #

Extract the CoreExpr from the EvExpr forms we build.

data ReadPrecEnv Source #

Every combinator GHC's derived readPrec uses, looked up once.

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.