I am making a server with Swift 5 and Vapor 3. When setting up a route I want to call a function from my controller that returns an optional like so:
//Person.swift
struct Person: Content {
...
}
//PersonController.swift
func update(_ request: Request) throws -> Future<Person> {
let uuid = try request.parameters.next(UUID.self)
return try request.content.decode(Person.self).flatMap { content in
request.withPooledConnection(to: DatabaseIdentifier<PostgreSQLDatabase>.psql) { connection in
/*
* No code completion beyond this point,
* even connection appears as type '_' instead of
* PostgreSQLConnection (not relevant to the question tho,
* just worth noting)
*/
if content.lastName != nil {
return connection.raw("Very long SQL query...")
.binds([...])
.first(decoding: Person.self)
}
return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)
}
}
}
router.put("people", UUID.parameter, use: personController.update)
But then I get this error
Cannot convert value of type '(Request) throws -> EventLoopFuture<Person?>' to expected argument type '(Request) throws -> _'
I see many instances when working with Vapor in which Xcode just gives up on autocompleting, and everything is just typed as _
. Mostly inside closures that are used as callbacks. It is VERY annoying, and quite frankly I am unsure if it is caused because of Vapor, Swift, or Xcode. It is a huge PITA but it all gets resolved once I compile, the types just get sorted out. However in this case it is just not working.
So the question is: Why is does Xcode say the expected type is (Request) throws -> _
when the actual definition for Request.put(_:use:)
requires a (Request) throws -> T
and how does that make a difference between T
being Future<Person>
and Future<Person?>
?