[SERVER-67528] Struct field in IDL cannot have a type of a variant that contains a long Created: 24/Jun/22  Updated: 06/Dec/22

Status: Open
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Davis Haupt (Inactive) Assignee: Backlog - Service Architecture
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Service Arch
Operating System: ALL
Steps To Reproduce:

Create an IDL struct with a field that has a variant containing a long:

structs:    
    SampleStruct:
        strict: true
        fields:
            f:
                unstable: true
                type:
                    variant: [int, long]

The field in the generated IDL struct has this type:

stdx::variant<std::int32_t, std::int64_t> _f; 

And will throw this error from within the generated parseProtected() function:

error: no viable overloaded '='
                _min = element._numberLong();
                ~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~
src/third_party/variant-1.4.0/include/mpark/variant.hpp:1643:14: note: candidate function not viable: no known conversion from 'long long' to 'const mpark::variant<int, long>' for 1st argument
    variant &operator=(const variant &) = default;
             ^
src/third_party/variant-1.4.0/include/mpark/variant.hpp:1644:14: note: candidate function not viable: no known conversion from 'long long' to 'mpark::variant<int, long>' for 1st argument
    variant &operator=(variant &&) = default;
             ^
src/third_party/variant-1.4.0/include/mpark/variant.hpp:1654:21: note: candidate template ignored: substitution failure [with Arg = long long, $1 = 0]: no type named 'type' in 'mpark::lib::cpp17::detail::invoke_result<void, mpark::detail::overload_impl<int, long>::impl<std::integer_sequence<unsigned long, 0, 1> >, long long &&>'
    inline variant &operator=(Arg &&arg) noexcept(
                    ^
1 error generated. 

Participants:

 Description   

It seems like there’s a mismatch between the type that the IDL uses to support longs (int64_t) and the type that the BSON library uses internally (long long) that shows up when trying to add long as a component with a variant.

I think this is due to a known mismatch in our codebase between long long used in the BSON library and int64_t used outside of it. My guess is that it’s not able to do an implicit cast through the variant implicit constructor.

A possible solution is to add an explicit cast from long long to int64_t when generating the parsing code for variant types, so that the line in the generated file reads:

_min = (int64_t) element._numberLong(); 

long long is defined as being at least 64 bits, and considering it's representing NumberLong BSONType here which is defined as being a 64-bit integer, I believe it is safe to cast the output of element._numberLong() to int64_t.

AC: Investigate whether this modification exposes any unexpected behavior on esoteric architectures, and also do some thinking of whether this change is a good idea at all. Themes include investigating the interaction between BSON and the IDL library, and potential upgrade/downgrade concerns. We could follow up with Storage Execution, who owns BSON more generally.



 Comments   
Comment by Davis Haupt (Inactive) [ 27/Jun/22 ]

We ended up using the Value type from value.idl and validating that the field contained one of our supported types in our own code, so this isn't urgent for us at the moment.

Generated at Thu Feb 08 06:08:22 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.