简体   繁体   中英

missing parameter type for expanded function for my function; not for another with same signature

Short form : I have a method with the same signature as Future.recover . Passing a partial function to Future 's version works. Passing the same PF to my version results in a missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5) missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5) missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5) error. What's the difference?

Longer form : I'm trying to implement the TracingFuture class discussed here in an attempt to trace errors across future boundaries. The basic technique is to wrap the Future in another class, TracingFuture , while adding a pseudo-stacktrace.

The code given in the blog post is missing the recover method from Future , so I've added it with the same signature:

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))

  }

}

For comparison, here's the equivalent chunk of code out of Future . Note that aside from the extra implicit parameters the signatures are the same.

trait Future[+T] extends Awaitable[T] {

  def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] =
    transform { _ recover pf }
}

Finally, my code that produces the compile error:

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]
}

And the error message:

[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]                                  ^

Once again, this code works with the Future.recover but I get a compile error with TracingFuture.recover . I don't understand why.

This SO question explains that the compiler knows the argument to the partial function must be a supertype of T but can't guarantee that. But why doesn't it run into that issue with Future.recover ?

And, of course, I'd like to know if there's anything I do about it other than rewriting the anonymous partial function to make the types explicit.

The problem is that TracingFuture has two overloaded recover methods: the one you added and the one you inherited from Future . When you only have one, it provides the expected type which is crucial for type inference, but with overloaded methods it doesn't work, as you see from Expected type was: ? .

You may think the compiler should notice types of function parameters are the same and so can still provide the expected type. And you would be right, but it was only fixed in Scala 2.12 .

Of course, then you'll run into trouble that the compiler has no way to tell which overload you want when only the implicit arguments are different.

Try to replace

val fMaintainers = x.recover {
  case err: Throwable ⇒
    logger.error("Failed to get list of user maintainers.", err)
    Vector.empty[Maintainer]
}

with

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM