简短格式:我的方法与Future.recover
具有相同的签名。将部分功能传递给Future
的版本可以正常工作。将相同的PF传递给我的版本会导致missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5)
错误。有什么区别?
更长时间:
我试图实施TracingFuture
类讨论here,试图追踪未来边界的错误。基本技术是将Future包装在另一个类TracingFuture
中,同时添加伪栈跟踪。
博客文章中提供的代码缺少recover
的{{1}}方法,因此我添加了相同的签名:
Future
为了比较,这里是class TracingFuture[+T](underlying: Future[T], val trace: Vector[FutureTraceElement]) extends Future[T] {
def recover[U >: T](pf: PartialFunction[Throwable, U]
)(implicit ec: ExecutionContext, enclosing: sourcecode.Enclosing, file: sourcecode.File,
line: sourcecode.Line): TracingFuture[U] = {
val recovered = underlying.recover(pf)
new TracingFuture[U](recovered, trace :+ FutureTraceElement(enclosing.value, "recover", file.value, line.value))
}
}
中等效的代码块。请注意,除了额外的隐式参数,签名是相同的。
Future
最后,我的代码产生了编译错误:
trait Future[+T] extends Awaitable[T] {
def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] =
transform { _ recover pf }
}
错误信息:
val x: TracingFuture[Vector[Maintainer]] = ... // code producing a TracingFuture
val fMaintainers = x.recover {
case err: Throwable ⇒
logger.error("Failed to get list of user maintainers.", err)
Vector.empty[Maintainer]
}
再次,此代码适用于[error] /Users/bwbecker/oat/src/oat3/modules/wapp/app/oat/wapp/dao/CronJobDAO.scala:273: missing parameter type for expanded function
[error] The argument types of an anonymous function must be fully known. (SLS 8.5)
[error] Expected type was: ?
[error] val fMaintainers = x.recover {
[error] ^
,但我收到Future.recover
的编译错误。我不明白为什么。
This SO question解释说编译器知道部分函数的参数必须是T的超类型但不能保证。但是为什么它不会遇到TracingFuture.recover
的问题?
当然,除了重写匿名部分功能以使类型明确外,我想知道我是否还有其他任何事情。
答案 0 :(得分:2)
问题是TracingFuture
有两个重载的recover
方法:您添加的方法和从Future
继承的方法。如果只有一个,它提供了对类型推断至关重要的预期类型,但是使用重载方法它不起作用,正如您从Expected type was: ?
看到的那样。
您可能认为编译器应该注意到函数参数的类型是相同的,因此仍然可以提供预期的类型。你会是对的,但是it was only fixed in Scala 2.12。
当然,如果只有隐式参数不同,那么编译器无法告诉你想要哪个重载会遇到麻烦。
答案 1 :(得分:1)
尝试替换
val fMaintainers = x.recover {
case err: Throwable ⇒
logger.error("Failed to get list of user maintainers.", err)
Vector.empty[Maintainer]
}
带
val fMaintainers = x.recover(PartialFunction[Throwable, Vector[Maintainer]] {
case err: Throwable ⇒
logger.error("Failed to get list of user maintainers.", err)
Vector.empty[Maintainer]
})
Why do I get a "missing parameter for expanded function" in one case and not the other?