Custom bit representations fail for single-constructor data types
As already noted in #2949: custom bit representations fail for data types with only a single constructor, e.g.,
data T = T0 Bool
{-# ANN module (DataReprAnn $(liftQ [t|T|]) 1
[ConstrRepr 'T0 0b0 0b0 [0b1]]) #-}
causes Clash to produce
<no location info>: error:
Clash error call:
Unexpected HWType: Bool
CallStack (from HasCallStack):
error, called at src/Clash/Netlist/Util.hs:316:10 in clash-lib-1.9.0-inplace:Clash.Netlist.Util
convertToCustomRepr, called at src/Clash/Netlist/Util.hs:356:8 in clash-lib-1.9.0-inplace:Clash.Netlist.Util
The utilized inner type does not matter. It can be Int, Bool, or something else. Clash always fails in this case.
Thanks to @DigitalBrains1 for making clear that this is a bug.
Data types with only a single constructor and field are reduced to just the field type here
https://github.com/clash-lang/clash-compiler/blob/4384800decf44ba51fc1fd083ff69691f0350ba1/clash-lib/src/Clash/Netlist/Util.hs#L472-L473
which then eventually gets passed to convertToCustomRepr checking that the number of constructor fields in the data representation matches with the custom one
https://github.com/clash-lang/clash-compiler/blob/4384800decf44ba51fc1fd083ff69691f0350ba1/clash-lib/src/Clash/Netlist/Util.hs#L286
However, nConstrs and cs both expect to only see sum and product types, which is why nConstrs already fails.
https://github.com/clash-lang/clash-compiler/blob/4384800decf44ba51fc1fd083ff69691f0350ba1/clash-lib/src/Clash/Netlist/Util.hs#L298-L316
Is there a reason to not return a singleton product type in mkADT for a single constructor and field?
I’ve forgotten the original reason, maybe some code archeology can recover it from the commit messages. If I were to have a guess it is that newtypes sometimes aren’t “constructed”, but “cast” and this was messing up the VHDL backend (creating VHDL that wouldn’t typecheck). And at the time “filtering” single field product types was the path of least resistance.