Question about record & variant with opt fields in light of forward compatibility

I have a question how CDKs should handle deserialization of record & variant with opt fields if the label of an opt field is not known by the interface definition.

I asked the AI on the docs, but the AI says it is not explicitly stated what to do.

Question 1: record

Is my understanding correct that if a canister interface is defined as:

record { field1: opt text; field2: opt int }

but it receives this:

record { new: opt nat}

It should just ignore the new, and since field1 & field2 are not there, it must all be decoded as null.

Question 2: variant

And does it work the same for variant? So, if a canister interface is defined as:

variant { field1: opt text; field2: opt int }

but it receives this:

variant { new: opt nat}

It should just ignore the new, and it must be decoded as null.

For records you are correct. For variants, since a variant value always is a single case, nulling out other cases is not meaningful – we would need to map the unknown case to some other allowed case, but there is no canonical way to do so.

Consequently, it works in a dual fashion, with opt on the outside. That is, if an interface has a parameter defined as

opt variant { field1 : text; field2 : int }

but receives a value of type

opt variant { new : nat }

then it is decoded as null.

As a consequence, if you want a variant to be forward-compatible, you should always wrap it in an opt.

1 Like

Thank you for that clarification.

Just to be 100% sure, in my example above, the variant { new: opt nat} should trap with an error that the parameter is not known. Is that correct?

@rossberg ,

I have a follow up question about the opt on the outside.

Does the opt behavior propagate into a record and then into the fields of a record?

For example, if the definition is:

opt record { field1: text; field2: variant { fieldv : int} }

But it receives this:

opt record { Newr: text; field2: variant { Newv : int} }

It is all valid and decodes to null?

(I am asking because I am implementing the Opt logic into the C++ CDK right now and want to do it correct)

Yes.

No, opt does not “propagate”. However, the general rule for opt is that it becomes null if the types cannot be made to match otherwise. That happens at the innermost opt where this fallback suffices to make the whole thing match.

1 Like