[SERVER-67983] The IDL generator cannot manage struct definitions that include an optional variant field Created: 12/Jul/22  Updated: 05/Dec/22

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

Type: Bug Priority: Major - P3
Reporter: Paolo Polato Assignee: Backlog - Service Architecture
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Text File generator.patch    
Assigned Teams:
Service Arch
Operating System: ALL
Steps To Reproduce:
  • Define a new IDL struct that includes an field of variant type, such as

    structs:
        CreateCommandRequest:
            strict: true
            fields:
                clusteredIndex:
                    type:
                        variant: [safeBool, ClusteredIndexSpec]
                    optional: true
                    unstable: false
    

  • Compile the server code

Expected outcome: the IDL generator should produce valid gen.h/cpp files

Observed outcome: the code produced by the IDL generator cannot be compiled

  • Sample from the generated code:

    void CreateCommand::parseProtected(const IDLParserErrorContext& ctxt, const BSONObj& bsonObject) {
    ... 
            else if (fieldName == kClusteredIndexFieldName) {
                if (MONGO_unlikely(usedFields[kClusteredIndexBit])) {
                    ctxt.throwDuplicateField(element);
                }
     
                usedFields.set(kClusteredIndexBit);
     
     
                const BSONType variantType = element.type();
                switch (variantType) {
                   ...
                case NumberDouble:
                {
                    _createCommandRequest.setClusteredIndex(boost::optional<stdx::variant<bool, mongo::ClusteredIndexSpec>>(element.trueValue()));
                    break;
                }
                case Object:
                    _createCommandRequest.setClusteredIndex(mongo::ClusteredIndexSpec::parse(ctxt, element.Obj())); // <-- THE OFFENDING LINE
                    break;
                }
     
    }
    

  • Compilation error:

    [210/983 ( 21%) 8.508s] Compiled build/optdebug/mongo/db/commands/create_gen.dyn.o
    FAILED: build/optdebug/mongo/db/commands/create_gen.dyn.o 
    export CCACHE_NOCPP2='1';export CCACHE_PREFIX='/home/ubuntu/mongo/build/scons/icecream/optdebug/run-icecc.sh';export ICECC_CLANG_REMOTE_CPP='1';export PATH='/opt/mongodbtoolchain/v3/bin:/usr/local/bin:/opt/bin:/bin:/usr/bin';/usr/bin/ccache /opt/mongodbtoolchain/v3/bin/clang++ @build/optdebug/mongo/db/commands/create_gen.dyn.o.rsp
    build/optdebug/mongo/db/commands/create_gen.cpp:1083:57: error: no viable conversion from 'mongo::ClusteredIndexSpec' to 'boost::optional<stdx::variant<bool, mongo::ClusteredIndexSpec> >'
                    _createCommandRequest.setClusteredIndex(mongo::ClusteredIndexSpec::parse(ctxt, element.Obj()));
                                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    src/third_party/boost/boost/optional/optional.hpp:934:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'boost::none_t' for 1st argument
        optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
        ^
    src/third_party/boost/boost/optional/optional.hpp:938:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'boost::optional<mpark::variant<bool, mongo::ClusteredIndexSpec> >::argument_type' (aka 'const mpark::variant<bool, mongo::ClusteredIndexSpec> &') for 1st argument
        optional ( argument_type val ) : base(optional_detail::init_value_tag(), val) {}
        ^
    src/third_party/boost/boost/optional/optional.hpp:943:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'boost::optional<mpark::variant<bool, mongo::ClusteredIndexSpec> >::rval_reference_type' (aka 'mpark::variant<bool, mongo::ClusteredIndexSpec> &&') for 1st argument
        optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), boost::forward<T>(val))
        ^
    src/third_party/boost/boost/optional/optional.hpp:1023:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'const boost::optional<mpark::variant<bool, mongo::ClusteredIndexSpec> > &' for 1st argument
        optional ( optional const& ) = default;
        ^
    src/third_party/boost/boost/optional/optional.hpp:1033:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'boost::optional<mpark::variant<bool, mongo::ClusteredIndexSpec> > &&' for 1st argument
        optional ( optional && ) = default;
        ^
    build/optdebug/mongo/db/commands/create_gen.h:188:92: note: passing argument to parameter 'value' here
        void setClusteredIndex(boost::optional<stdx::variant<bool, mongo::ClusteredIndexSpec>> value) {  _clusteredIndex = std::move(value);  }
                                                                                               ^
    build/optdebug/mongo/db/commands/create_gen.cpp:1493:57: error: no viable conversion from 'mongo::ClusteredIndexSpec' to 'boost::optional<stdx::variant<bool, mongo::ClusteredIndexSpec> >'
                    _createCommandRequest.setClusteredIndex(mongo::ClusteredIndexSpec::parse(ctxt, element.Obj()));
                                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    src/third_party/boost/boost/optional/optional.hpp:934:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'boost::none_t' for 1st argument
        optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
        ^
    src/third_party/boost/boost/optional/optional.hpp:938:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'boost::optional<mpark::variant<bool, mongo::ClusteredIndexSpec> >::argument_type' (aka 'const mpark::variant<bool, mongo::ClusteredIndexSpec> &') for 1st argument
        optional ( argument_type val ) : base(optional_detail::init_value_tag(), val) {}
        ^
    src/third_party/boost/boost/optional/optional.hpp:943:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'boost::optional<mpark::variant<bool, mongo::ClusteredIndexSpec> >::rval_reference_type' (aka 'mpark::variant<bool, mongo::ClusteredIndexSpec> &&') for 1st argument
        optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), boost::forward<T>(val))
        ^
    src/third_party/boost/boost/optional/optional.hpp:1023:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'const boost::optional<mpark::variant<bool, mongo::ClusteredIndexSpec> > &' for 1st argument
        optional ( optional const& ) = default;
        ^
    src/third_party/boost/boost/optional/optional.hpp:1033:5: note: candidate constructor not viable: no known conversion from 'mongo::ClusteredIndexSpec' to 'boost::optional<mpark::variant<bool, mongo::ClusteredIndexSpec> > &&' for 1st argument
        optional ( optional && ) = default;
        ^
    build/optdebug/mongo/db/commands/create_gen.h:188:92: note: passing argument to parameter 'value' here
        void setClusteredIndex(boost::optional<stdx::variant<bool, mongo::ClusteredIndexSpec>> value) {  _clusteredIndex = std::move(value);  }
    

Participants:

 Description   

See the "steps to reproduce" section.



 Comments   
Comment by Mathias Stearn [ 12/Jul/22 ]

Meta-comment: I think any time the IDL generator generates C++ code that doesn't compile it should be considered a bug worth fixing. Even if it is a case we don't intend to support (either in the short or mid term), we should at least output a clear error message saying so, rather than generating bad C++ code.

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