Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-62324

Failure to build mongo::unique_function uses with MSVS 2022 in C++20 mode

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Critical - P2 Critical - P2
    • 5.3.0
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None
    • Fully Compatible
    • ALL
    • Service Arch 2022-10-17

      While working on SERVER-62234 and SERVER-62235, I've run into issues building the tree with MSVS 2022 in C++20 mode. The issues all appear to revolve around mongo::unique_function, and probably, more narrowly, its Functor taking constuctor.

      One instance happens in exit.hpp, where it appears unable to decide which sort of unique_function is to be created from a lambda, despite the fact that the lambda is clearly a good type match for one and not the other option:

      Z:\data\acm\src\mongo\src\mongo/util/exit.h(81,87): error C2665: 'mongo::registerShutdownTask': none of the 2 overloads could convert all the argument types
          registerShutdownTask([task = std::move(task)](const ShutdownTaskArgs&) { task(); });
                                                                                            ^
      Z:\data\acm\src\mongo\src\mongo/util/exit.h(80,13): note: could be 'void mongo::registerShutdownTask(mongo::unique_function<void (void)>)'
      inline void registerShutdownTask(unique_function<void()> task) {
                  ^
      Z:\data\acm\src\mongo\src\mongo/util/exit.h(75,6): note: or       'void mongo::registerShutdownTask(mongo::unique_function<void (const mongo::ShutdownTaskArgs &)>)'
      void registerShutdownTask(unique_function<void(const ShutdownTaskArgs& shutdownArgs)>);
           ^
      Z:\data\acm\src\mongo\src\mongo/util/exit.h(81,87): note: while trying to match the argument list '(mongo::registerShutdownTask::<lambda_1>)'
          registerShutdownTask([task = std::move(task)](const ShutdownTaskArgs&) { task(); });
      

      Another example is in mongo/util/out_of_line_executor.h, where it appears that what looks like a perfectly good match isn't seen as available:

      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(143,20): error C2440: '<function-style-cast>': cannot convert from 'mongo::GuaranteedExecutor::e
      nforceRunOnce::<lambda_1>' to 'mongo::OutOfLineExecutor::Task'
              return Task([task = std::move(task), guard = RunOnceGuard()](Status status) mutable {
                         ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(149,1): note: No constructor could take the source type, or constructor overload resolution was
      ambiguous
              });
      ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(154,1): error C3313: 'sureFunc': variable cannot have the type 'void'
              auto sureFunc = enforceRunOnce(std::move(func));
      ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(155,1): error C3536: 'sureFunc': cannot be used before it is initialized
              _exec->schedule(std::move(sureFunc));
      ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(155,1): error C2664: 'void mongo::OutOfLineExecutor::schedule(mongo::OutOfLineExecutor::Task)': cannot convert argument 1 from 'int' to 'mongo::OutOfLineExecutor::Task'
              _exec->schedule(std::move(sureFunc));
      ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(155,1): note: No constructor could take the source type, or constructor overload resolution was ambiguous
              _exec->schedule(std::move(sureFunc));
      ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(118,18): note: see declaration of 'mongo::OutOfLineExecutor::schedule'
          virtual void schedule(Task func) = 0;
                       ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(181,19): error C2664: 'void mongo::OutOfLineExecutor::schedule(mongo::OutOfLineExecutor::Task)': cannot convert argument 1 from 'mongo::GuaranteedExecutorWithFallback::schedule::<lambda_1>' to 'mongo::OutOfLineExecutor::Task'
              _preferred->schedule([func = std::move(func), fallback = _fallback](Status status) mutable {
                        ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(190,9): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
              });
              ^
      Z:\data\acm\src\mongo\src\mongo/util/out_of_line_executor.h(118,18): note: see declaration of 'mongo::OutOfLineExecutor::schedule'
          virtual void schedule(Task func) = 0;
                       ^
      

      A fix will be required for these issues in order to stand up a C++20 enabled canary builder with MSVS 2022, which is a critical path step towards moving to the v4 toolchains and on to C++20 enablement.

      Note that this code works with GCC 8.3/11, clang 7/12, and Xcode 10/13 in both C++17 and C++20 mode, as well as with VS 2019 in C++17 mode and VS 2022 in C++17 mode, so it is entirely possible that this is a C++20 mode VS 2022 specific issue. Some workaround would still be required though.

            Assignee:
            billy.donahue@mongodb.com Billy Donahue
            Reporter:
            andrew.morrow@mongodb.com Andrew Morrow (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: