real-logic / simple-binary-encoding

Simple Binary Encoding (SBE) - High Performance Message Codec
Apache License 2.0
3.12k stars 524 forks source link

[Rust] Invalid codegen for composite type with sinceVersion #1028

Open marciorasf opened 1 day ago

marciorasf commented 1 day ago

For the sample schema:

<sbe:messageSchema
    xmlns:ns2="http://www.fixprotocol.org/ns/simple/1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:sbe="http://fixprotocol.io/2016/sbe"
    package="b3.entrypoint.fixp.sbe"
    id="1"
    version="4"
    semanticVersion="8.2.3"
    description="B3 Binary Entrypoint FIXP messages"
    byteOrder="littleEndian"
    xsi:schemaLocation="http://fixprotocol.io/2016/sbe sbe.xsd">
    <types>
        <set name="EventIndicator" encodingType="uint8" description="Set of indicators for a given event. First use case: indicates possible retransmission of message during recovery process." sinceVersion="4">
            <choice name="PossResend" description="1=Message is sent during recovery process, 0=Normal message.">0</choice>
        </set>
        <composite name="messageHeader" description="Message identifiers and length of message root.">
            <type name="blockLength" primitiveType="uint16" description="Length of the root of the FIX message contained before repeating groups or variable/conditions fields."/>
            <type name="templateId" primitiveType="uint16" description="Template ID used to encode the message."/>
            <type name="schemaId" primitiveType="uint16" description="ID of the system publishing the message."/>
            <type name="version" primitiveType="uint16" description="Schema version."/>
        </composite>
        <composite name="OutboundBusinessHeader" description="Header used for outbound business messages.">
            <ref name="eventIndicator" type="EventIndicator" sinceVersion="4"/>
        </composite>
    </types>

    <sbe:message name="ExecutionReport_New" id="200" description="Execution Report - New message is sent in response to a NewOrderSingle or SimpleNewOrder messages, or also from a restated iceberg order.">
        <field name="businessHeader" type="OutboundBusinessHeader" id="35524" description="Common header to all outbound business messages."/>
    </sbe:message>
</sbe:messageSchema>

CLI tool 1.33.2 generates Rust code that doesn't compile due to:

error[E0599]: the method `acting_version` exists for reference `&OutboundBusinessHeaderDecoder<P>`, but its trait bounds were not satisfied
   --> crates/b3_entrypoint_fixp_sbe/src/outbound_business_header_codec.rs:101:21
    |
58  |     pub struct OutboundBusinessHeaderDecoder<P> {
    |     ------------------------------------------- doesn't satisfy `OutboundBusinessHeaderDecoder<P>: ActingVersion`
...
101 |             if self.acting_version() < 4 {
    |                     ^^^^^^^^^^^^^^ method cannot be called on `&OutboundBusinessHeaderDecoder<P>` due to unsatisfied trait bounds    

OutboundBusinessHeaderDecoder does implement self.acting_version(), but just for a P: Reader<'a> + ActingVersion + Default:

impl<'a, P> ActingVersion for OutboundBusinessHeaderDecoder<P>
where
    P: Reader<'a> + ActingVersion + Default,
{
    #[inline]
    fn acting_version(&self) -> u16 {
        self.parent.as_ref().unwrap().acting_version()
    }
}

And error occurs because it's trying to use self.acting_version() for a P that does not implement ActingVersion:

impl<'a, P> OutboundBusinessHeaderDecoder<P>
where
    P: Reader<'a> + Default,
{
    /// BIT SET DECODER
    #[inline]
    pub fn event_indicator(&self) -> event_indicator::EventIndicator {
        if self.acting_version() < 4 {
            return event_indicator::EventIndicator::default();
        }

        event_indicator::EventIndicator::new(self.get_buf().get_u8_at(self.offset))
    }
}

It seems that this problem is a continuation of this one: https://github.com/real-logic/simple-binary-encoding/issues/984 which was already closed.