Skip to content

deriveAutoReg does not add superclass constraints as required constraints to generated instance. #3101

@rowanG077

Description

@rowanG077

Motivating example:

data MsgConfig = MsgConfig
  { _msgChannelWidth :: Nat
  , _msgDataLen :: Nat
  }

type family MsgChannelWidth (cfg :: MsgConfig) :: Nat where
  MsgChannelWidth ('MsgConfig x _) = x

type family MsgDataLen (cfg :: MsgConfig) :: Nat where
  MsgDataLen ('MsgConfig _ x) = x

type KnownMsgConfig cfg = (KnownNat (MsgDataLen cfg), KnownNat (MsgChannelWidth cfg))

data Message (cfg :: MsgConfig) = Status
  { _msg_channel :: Unsigned (MsgChannelWidth cfg)
  , _msg_data :: Vec (MsgDataLen cfg) (Unsigned 8)
  , _msg_chksum  :: Unsigned 4
  }
  deriving (Bundle, Generic)
deriving instance (KnownMsgConfig cfg) => NFDataX (Message cfg)
deriving instance (KnownMsgConfig cfg) => BitPack (Message cfg)
deriveAutoReg ''Message

Which gives an error:

    • Could not deduce ‘KnownNat (MsgChannelWidth cfg)’
        arising from the superclasses of an instance declaration
      from the context: KnownNat (MsgDataLen cfg)
        bound by the instance declaration at src/Protocols.hs:97:1-23
    • In the instance declaration for ‘AutoReg (Message cfg)’
   |
97 | deriveAutoReg ''Message

And this is because deriveAutoReg, naively (?), assumes the NFDataX constraint on AutoReg can never introduce additional constraints beyond what AutoReg itself directly implies.

In this case NFDataX Requires both (KnownNat (MsgDataLen cfg), KnownNat (MsgChannelWidth cfg)) but AutoReg only needs KnownNat (MsgDataLen cfg) directly. So KnownNat (MsgChannelWidth cfg) is not added to the instance and the error is given.

This example can be re-written to work. But it's a footgun imo and I don't see/know a reason why it shouldn't also look through what constraints are required via superclasses.

See: https://clash-lang.discourse.group/t/deriveautoreg-with-superclass-constraints/100

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions