ghc-9.6.3: The GHC API

Safe Haskell | Safe-Inferred
Language | Haskell2010

GHC.Tc.Deriv.Utils

Description

Error-checking and other utilities for `deriving` clauses or declarations.

Synopsis

- type DerivM = ReaderT DerivEnv TcRn
- data DerivEnv = DerivEnv {
  - denv_overlap_mode :: Maybe OverlapMode
  - denv_tvs :: [TyVar]
  - denv_cls :: Class
  - denv_inst_tys :: [Type]
  - denv_ctxt :: DerivContext
  - denv_skol_info :: SkolemInfo
  - denv_strat :: Maybe (DerivStrategy GhcTc)
  }
- data DerivSpec theta = DS {
  - ds_loc :: SrcSpan
  - ds_name :: Name
  - ds_tvs :: [TyVar]
  - ds_theta :: theta
  - ds_cls :: Class
  - ds_tys :: [Type]
  - ds_skol_info :: SkolemInfo
  - ds_user_ctxt :: UserTypeCtxt
  - ds_overlap :: Maybe OverlapMode
  - ds_standalone_wildcard :: Maybe SrcSpan
  - ds_mechanism :: DerivSpecMechanism
  }
- pprDerivSpec :: Outputable theta => DerivSpec theta -> SDoc
- setDerivSpecTheta :: theta' -> DerivSpec theta -> DerivSpec theta'
- zonkDerivSpec :: DerivSpec ThetaType -> TcM (DerivSpec ThetaType)
- data DerivSpecMechanism
  - = DerivSpecStock {
    - dsm_stock_dit :: DerivInstTys
    - dsm_stock_gen_fns :: StockGenFns
    }
  - | DerivSpecNewtype {
    - dsm_newtype_dit :: DerivInstTys
    - dsm_newtype_rep_ty :: Type
    }
  - | DerivSpecAnyClass
  - | DerivSpecVia {
    - dsm_via_cls_tys :: [Type]
    - dsm_via_inst_ty :: Type
    - dsm_via_ty :: Type
    }
- derivSpecMechanismToStrategy :: DerivSpecMechanism -> DerivStrategy GhcTc
- isDerivSpecStock :: DerivSpecMechanism -> Bool
- isDerivSpecNewtype :: DerivSpecMechanism -> Bool
- isDerivSpecAnyClass :: DerivSpecMechanism -> Bool
- isDerivSpecVia :: DerivSpecMechanism -> Bool
- zonkDerivSpecMechanism :: ZonkEnv -> DerivSpecMechanism -> TcM DerivSpecMechanism
- data DerivContext
  - = InferContext (Maybe SrcSpan)
  - | SupplyContext ThetaType
- data OriginativeDerivStatus
  - = CanDeriveStock StockGenFns
  - | StockClassError !DeriveInstanceErrReason
  - | CanDeriveAnyClass
  - | NonDerivableClass
- data StockGenFns = StockGenFns {
  - stock_gen_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, [LSig GhcPs], Bag AuxBindSpec, [Name])
  - stock_gen_fam_insts :: SrcSpan -> DerivInstTys -> TcM [FamInst]
  }
- isStandaloneDeriv :: DerivM Bool
- isStandaloneWildcardDeriv :: DerivM Bool
- askDerivUserTypeCtxt :: DerivM UserTypeCtxt
- mkDerivOrigin :: Bool -> CtOrigin
- data PredSpec
  - = SimplePredSpec {
    - sps_pred :: TcPredType
    - sps_origin :: CtOrigin
    - sps_type_or_kind :: TypeOrKind
    }
  - | SubTypePredSpec {
    - stps_ty_actual :: TcSigmaType
    - stps_ty_expected :: TcSigmaType
    - stps_origin :: CtOrigin
    }
- type ThetaSpec = [PredSpec]
- mkDirectThetaSpec :: CtOrigin -> TypeOrKind -> ThetaType -> ThetaSpec
- substPredSpec :: HasCallStack => Subst -> PredSpec -> PredSpec
- captureThetaSpecConstraints :: UserTypeCtxt -> ThetaSpec -> TcM (TcLevel, WantedConstraints)
- checkOriginativeSideConditions :: DerivInstTys -> DerivM OriginativeDerivStatus
- hasStockDeriving :: Class -> Maybe StockGenFns
- std_class_via_coercible :: Class -> Bool
- non_coercible_class :: Class -> Bool
- newDerivClsInst :: DerivSpec ThetaType -> TcM ClsInst
- extendLocalInstEnv :: [ClsInst] -> TcM a -> TcM a

# Documentation

type DerivM = ReaderT DerivEnv TcRn Source #

To avoid having to manually plumb everything in `DerivEnv` throughout various functions in GHC.Tc.Deriv and GHC.Tc.Deriv.Infer, we use `DerivM`, which is a simple reader around `TcRn`.

data DerivEnv Source #

Contains all of the information known about a derived instance when determining what its `EarlyDerivSpec` should be. See `Note [DerivEnv and DerivSpecMechanism]`.

Constructors

DerivEnv |

Fields

- denv_overlap_mode :: Maybe OverlapMode

  Is this an overlapping instance?

- denv_tvs :: [TyVar]

  Universally quantified type variables in the instance. If the `denv_ctxt` is `InferContext`, these will be `TcTyVar` skolems. If the `denv_ctxt` is `SupplyContext`, these will be ordinary `TyVar`s. See `Note [Overlap and deriving]` in GHC.Tc.Deriv.Infer.

  All type variables that appear in the `denv_inst_tys`, `denv_ctxt`, `denv_skol_info`, and `denv_strat` should come from `denv_tvs`.

- denv_cls :: Class

  Class for which we need to derive an instance

- denv_inst_tys :: [Type]

  All arguments to `denv_cls` in the derived instance.

- denv_ctxt :: DerivContext

  ``SupplyContext` theta` for standalone deriving (where `theta` is the context of the instance). `InferContext` for `deriving` clauses, or for standalone deriving that uses a wildcard constraint. See `Note [Inferring the instance context]`.

- denv_skol_info :: SkolemInfo

  The `SkolemInfo` used to skolemise the `denv_tvs` in the case where the `denv_ctxt` is `InferContext`.

- denv_strat :: Maybe (DerivStrategy GhcTc)

  `Just` if user requests a particular deriving strategy. Otherwise, `Nothing`.

#### Instances

Instances details

Outputable DerivEnv Source # |
Instance details Defined in GHC.Tc.Deriv.Utils Methods ppr :: DerivEnv -> SDoc Source #

data DerivSpec theta Source #

Constructors

DS |

Fields

- ds_loc :: SrcSpan
- ds_name :: Name
- ds_tvs :: [TyVar]
- ds_theta :: theta
- ds_cls :: Class
- ds_tys :: [Type]
- ds_skol_info :: SkolemInfo
- ds_user_ctxt :: UserTypeCtxt
- ds_overlap :: Maybe OverlapMode
- ds_standalone_wildcard :: Maybe SrcSpan
- ds_mechanism :: DerivSpecMechanism

#### Instances

Instances details

Outputable theta => Outputable (DerivSpec theta) Source # |
Instance details Defined in GHC.Tc.Deriv.Utils Methods ppr :: DerivSpec theta -> SDoc Source #

pprDerivSpec :: Outputable theta => DerivSpec theta -> SDoc Source #

setDerivSpecTheta :: theta' -> DerivSpec theta -> DerivSpec theta' Source #

Set the `ds_theta` in a `DerivSpec`.

zonkDerivSpec :: DerivSpec ThetaType -> TcM (DerivSpec ThetaType) Source #

Zonk the `TcTyVar`s in a `DerivSpec` to `TyVar`s. See `Note [What is zonking?]` in GHC.Tc.Utils.TcMType.

This is only used in the final zonking step when inferring the context for a derived instance. See `Note [Overlap and deriving]` in GHC.Tc.Deriv.Infer.

data DerivSpecMechanism Source #

What action to take in order to derive a class instance. See `Note [DerivEnv and DerivSpecMechanism]`, as well as `Note [Deriving strategies]` in GHC.Tc.Deriv.

Constructors

DerivSpecStock | "Standard" classes

Fields

- dsm_stock_dit :: DerivInstTys

  Information about the arguments to the class in the derived instance, including what type constructor the last argument is headed by. See `Note [DerivEnv and DerivSpecMechanism]`.

- dsm_stock_gen_fns :: StockGenFns

  How to generate the instance bindings and associated type family instances.

DerivSpecNewtype

    GeneralizedNewtypeDeriving

Fields

- dsm_newtype_dit :: DerivInstTys

  Information about the arguments to the class in the derived instance, including what type constructor the last argument is headed by. See `Note [DerivEnv and DerivSpecMechanism]`.

- dsm_newtype_rep_ty :: Type

  The newtype rep type.

DerivSpecAnyClass

    DeriveAnyClass

DerivSpecVia

    DerivingVia

Fields

- dsm_via_cls_tys :: [Type]

  All arguments to the class besides the last one.

- dsm_via_inst_ty :: Type

  The last argument to the class.

- dsm_via_ty :: Type

  The `via` type

#### Instances

Instances details

Outputable DerivSpecMechanism Source # |
Instance details Defined in GHC.Tc.Deriv.Utils Methods ppr :: DerivSpecMechanism -> SDoc Source #

derivSpecMechanismToStrategy :: DerivSpecMechanism -> DerivStrategy GhcTc Source #

Convert a `DerivSpecMechanism` to its corresponding `DerivStrategy`.

isDerivSpecStock :: DerivSpecMechanism -> Bool Source #

isDerivSpecNewtype :: DerivSpecMechanism -> Bool Source #

isDerivSpecAnyClass :: DerivSpecMechanism -> Bool Source #

isDerivSpecVia :: DerivSpecMechanism -> Bool Source #

zonkDerivSpecMechanism :: ZonkEnv -> DerivSpecMechanism -> TcM DerivSpecMechanism Source #

Zonk the `TcTyVar`s in a `DerivSpecMechanism` to `TyVar`s. See `Note [What is zonking?]` in GHC.Tc.Utils.TcMType.

This is only used in the final zonking step when inferring the context for a derived instance. See `Note [Overlap and deriving]` in GHC.Tc.Deriv.Infer.

data DerivContext Source #

Whether GHC is processing a `deriving` clause or a standalone deriving declaration.

Constructors

InferContext (Maybe SrcSpan)

`'InferContext mb_wildcard` is either:

- A `deriving` clause (in which case `mb_wildcard` is `Nothing`).
- A standalone deriving declaration with an extra-constraints wildcard as the context (in which case `mb_wildcard` is ``Just` loc`, where `loc` is the location of the wildcard.

GHC should infer the context.

SupplyContext ThetaType | ``SupplyContext` theta` is a standalone deriving declaration, where `theta` is the context supplied by the user.

#### Instances

Instances details

Outputable DerivContext Source # |
Instance details Defined in GHC.Tc.Deriv.Utils Methods ppr :: DerivContext -> SDoc Source #

data OriginativeDerivStatus Source #

Records whether a particular class can be derived by way of an originative deriving strategy (i.e., `stock` or `anyclass`).

See `Note [Deriving strategies]` in GHC.Tc.Deriv.

Constructors

CanDeriveStock StockGenFns |
StockClassError !DeriveInstanceErrReason |
CanDeriveAnyClass |
NonDerivableClass |

data StockGenFns Source #

Describes how to generate instance bindings (`stock_gen_binds`) and associated type family instances (`stock_gen_fam_insts`) for a particular stock-derived instance.

Constructors

StockGenFns |

Fields

- stock_gen_binds :: SrcSpan -> DerivInstTys -> TcM (LHsBinds GhcPs, [LSig GhcPs], Bag AuxBindSpec, [Name])

  Describes how to generate instance bindings for a stock-derived instance.

  This function takes two arguments:

  1. `SrcSpan`: the source location where the instance is being derived. This will eventually be instantiated with the `ds_loc` field of a `DerivSpec`.
  2. `DerivInstTys`: information about the argument types to which a class is applied in a derived instance. This will eventually be instantiated with the `dsm_stock_dit` field of a `DerivSpecMechanism`.

  This function returns four things:

  1. ``LHsBinds` `GhcPass``: The derived instance's function bindings (e.g., `compare (T x) (T y) = compare x y`)
  2. `[`LSig` `GhcPass`]`: A list of instance specific signatures/pragmas. Most likely `INLINE` pragmas for class methods.
  3. ``Bag` `AuxBindSpec``: Auxiliary bindings needed to support the derived instance. As examples, derived `Eq` and `Ord` instances sometimes require top-level `con2tag` functions. See `Note [Auxiliary binders]` in GHC.Tc.Deriv.Generate.
  4. `[`Name`]`: A list of Names for which `-Wunused-binds` should be suppressed. This is used to suppress unused warnings for record selectors when deriving `Read`, `Show`, or `Generic`. See `Note [Deriving and unused record selectors]`.
- stock_gen_fam_insts :: SrcSpan -> DerivInstTys -> TcM [FamInst]

  Describes how to generate associated type family instances for a stock-derived instance. This function takes the same arguments as the `stock_gen_binds` function but returns a list of `FamInst`s instead. Generating type family instances is done separately from `stock_gen_binds` since the type family instances must be generated before the instance bindings can be typechecked. See `Note [Staging of tcDeriving]` in GHC.Tc.Deriv.

isStandaloneDeriv :: DerivM Bool Source #

Is GHC processing a standalone deriving declaration?

isStandaloneWildcardDeriv :: DerivM Bool Source #

Is GHC processing a standalone deriving declaration with an extra-constraints wildcard as the context? (e.g., `deriving instance _ => Eq (Foo a)`)

askDerivUserTypeCtxt :: DerivM UserTypeCtxt Source #

Return `InstDeclCtxt` if processing with a standalone `deriving` declaration or `DerivClauseCtxt` if processing a `deriving` clause.

mkDerivOrigin :: Bool -> CtOrigin Source #

``mkDerivOrigin` wc` returns `StandAloneDerivOrigin` if `wc` is `True`, and `DerivClauseOrigin` if `wc` is `False`. Useful for error-reporting.

data PredSpec Source #

A `PredSpec` specifies a constraint to emitted when inferring the instance context for a derived instance in `simplifyInfer`.

Constructors

SimplePredSpec | An ordinary `PredSpec` that directly stores a `PredType`, which will be emitted as a wanted constraint in the constraint solving machinery. This is the simple case, as there are no skolems, metavariables, or given constraints involved.

Fields

- sps_pred :: TcPredType

  The constraint to emit as a wanted

- sps_origin :: CtOrigin

  The origin of the constraint

- sps_type_or_kind :: TypeOrKind

  Whether the constraint is a type or kind

SubTypePredSpec | A special `PredSpec` that is only used by `DeriveAnyClass`. This will check if `stps_ty_actual` is a subtype of (i.e., more polymorphic than) `stps_ty_expected` in the constraint solving machinery, emitting an implication constraint as a side effect. For more details on how this works, see `Note [Gathering and simplifying constraints for DeriveAnyClass]` in GHC.Tc.Deriv.Infer.

Fields

- stps_ty_actual :: TcSigmaType

  The actual type. In the context of `DeriveAnyClass`, this is the default method type signature.

- stps_ty_expected :: TcSigmaType

  The expected type. In the context of `DeriveAnyClass`, this is the original method type signature.

- stps_origin :: CtOrigin

  The origin of the constraint

#### Instances

Instances details

Outputable PredSpec Source # |
Instance details Defined in GHC.Tc.Deriv.Utils Methods ppr :: PredSpec -> SDoc Source #

type ThetaSpec = [PredSpec] Source #

A list of `PredSpec` constraints to simplify when inferring a derived instance's context. For the `stock`, `newtype`, and `via` deriving strategies, these will consist of `SimplePredSpec`s, and for `DeriveAnyClass`, these will consist of `SubTypePredSpec`s. Here is an example to illustrate the latter:

    class Foo a where
      bar :: forall b. Ix b => a -> b -> String
      default bar :: forall y. (Show a, Ix y) => a -> y -> String
      bar x y = show x ++ show (range (y, y))

      baz :: Eq a => a -> a -> Bool
      default baz :: Ord a => a -> a -> Bool
      baz x y = compare x y == EQ

    data Quux q = Quux deriving anyclass Foo

Then it would generate two `SubTypePredSpec`s, one for each method:

    [ SubTypePredSpec
        { stps_ty_actual   = forall y. (Show (Quux q), Ix y) => Quux q -> y -> String
        , stps_ty_expected = forall b.                (Ix b) => Quux q -> b -> String
        , stps_ty_origin   = DerivClauseCtxt
        }
    , SubTypePredSpec
        { stps_ty_actual   = Ord (Quux q) => Quux q -> Quux q -> Bool
        , stps_ty_expected = Eq  (Quux q) => Quux q -> Quux q -> Bool
        , stps_ty_origin   = DerivClauseCtxt
        }
    ]

(Note that the type variable `q` is bound by the data type `Quux`, and thus appears free in the `stps_ty_actual`s and `stps_ty_expected`s.)

See `Note [Gathering and simplifying constraints for DeriveAnyClass]` in GHC.Tc.Deriv.Infer for an explanation of how these `SubTypePredSpec`s are used to compute implication constraints.

mkDirectThetaSpec :: CtOrigin -> TypeOrKind -> ThetaType -> ThetaSpec Source #

Build a list of `SimplePredSpec`s, using the supplied `CtOrigin` and `TypeOrKind` values for each `PredType`.

substPredSpec :: HasCallStack => Subst -> PredSpec -> PredSpec Source #

captureThetaSpecConstraints Source #

Arguments

:: UserTypeCtxt | Used to inform error messages as to whether we are in a `deriving` clause or a standalone `deriving` declaration
-> ThetaSpec | The specs from which constraints will be created
-> TcM (TcLevel, WantedConstraints) |

Capture wanted constraints from a `ThetaSpec`.

checkOriginativeSideConditions :: DerivInstTys -> DerivM OriginativeDerivStatus Source #

hasStockDeriving :: Class -> Maybe StockGenFns Source #

std_class_via_coercible :: Class -> Bool Source #

non_coercible_class :: Class -> Bool Source #

newDerivClsInst :: DerivSpec ThetaType -> TcM ClsInst Source #

extendLocalInstEnv :: [ClsInst] -> TcM a -> TcM a Source #