[SERVER-55261] Lambdas passed to ExecutorFuture<T>::onError have to manually specify T or StatusWith<T> return type Created: 17/Mar/21  Updated: 06/Dec/22

Status: Backlog
Project: Core Server
Component/s: Internal Code
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Major - P3
Reporter: Blake Oler Assignee: Backlog - Service Architecture
Resolution: Unresolved Votes: 0
Labels: sa-remove-fv-backlog-22
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Service Arch
Participants:

 Description   

Example:

.then([this, executor] { return ExecutorFuture<T>(executor); })
.onError([](Status status) {
    return status;
}
...

will not compile, but

.then([this, executor] { return ExecutorFuture<T>(executor); })
.onError([](Status status) -> StatusWith<T> {
    return status;
}
...

will.

This is because the template deduction has trouble deducing that the onError returns a StatusWith<T> based on the previous continuation returning a non-void Future type.

An example compiler error is arcane and almost impossible to diagnose.

src/mongo/db/s/resharding/resharding_coordinator_service.cpp: In member function 'virtual mongo::SemiFuture<void> mongo::ReshardingCoordinatorService::ReshardingCoordinator::run(std::shared_ptr<mongo::executor::ScopedTaskExecutor>, const mongo::CancelationToken&)':
src/mongo/db/s/resharding/resharding_coordinator_service.cpp:1097:10: error: no matching function for call to 'mongo::ExecutorFuture<mongo::ReshardingCoordinatorDocument>::onError(mongo::ReshardingCoordinatorService::ReshardingCoordinator::run(std::shared_ptr<mongo::executor::ScopedTaskExecutor>, const mongo::CancelationToken&)::<lambda(mongo::Status)>)'
In file included from src/mongo/db/baton.h:35,
                 from src/mongo/transport/session.h:35,
                 from src/mongo/db/service_context.h:44,
                 from src/mongo/db/client.h:43,
                 from src/mongo/db/operation_context.h:36,
                 from src/mongo/transport/transport_layer.h:37,
                 from src/mongo/client/mongo_uri.h:43,
                 from src/mongo/client/authenticate.h:40,
                 from src/mongo/client/dbclient_base.h:36,
                 from src/mongo/db/pipeline/process_interface/mongo_process_interface.h:39,
                 from src/mongo/db/repl/primary_only_service.h:40,
                 from src/mongo/db/s/resharding/resharding_coordinator_service.h:32,
                 from src/mongo/db/s/resharding/resharding_coordinator_service.cpp:32:
src/mongo/util/future.h:665:23: note: candidate: 'template<class Func, typename std::enable_if<isCallableR<mongo::ReshardingCoordinatorDocument, Func, mongo::Status>, int>::type <anonymous> > mongo::ExecutorFuture<T> mongo::ExecutorFuture<T>::onError(Func&&) && [with Func = Func; typename std::enable_if<isCallableR<T, Func, mongo::Status>, int>::type <anonymous> = <enumerator>; T = mongo::ReshardingCoordinatorDocument]'
src/mongo/util/future.h:665:23: note:   template argument deduction/substitution failed:
src/mongo/util/future.h:664:77: error: no type named 'type' in 'struct std::enable_if<false, int>'
src/mongo/util/future.h:673:23: note: candidate: 'template<mongo::ErrorCodes::Error code, class Func, typename std::enable_if<isCallableR<mongo::ReshardingCoordinatorDocument, Func, mongo::Status>, int>::type <anonymous> > mongo::ExecutorFuture<T> mongo::ExecutorFuture<T>::onError(Func&&) && [with mongo::ErrorCodes::Error code = code; Func = Func; typename std::enable_if<isCallableR<T, Func, mongo::Status>, int>::type <anonymous> = <enumerator>; T = mongo::ReshardingCoordinatorDocument]'
src/mongo/util/future.h:673:23: note:   template argument deduction/substitution failed:
src/mongo/db/s/resharding/resharding_coordinator_service.cpp:1097:10: note:   couldn't deduce template parameter 'code'

This ticket is either to improve the error message or prevent the need to specify the return type.



 Comments   
Comment by Mathias Stearn [ 17/Mar/21 ]

This is documented at https://github.com/mongodb/mongo/blob/8ae44d4f3557e08d8a2e54f92e7395b46ea62859/src/mongo/util/future.h#L425-L432 The reason you need to return a T is that onError cannot change the return type. You can't just return a Status (except for Future<void>), because we wouldn't have a T object to propagate if you returned Status::OK().

Generated at Thu Feb 08 05:35:58 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.