danny.lesnik
danny.lesnik

Reputation: 18639

Scala Type Erasure warning in Play Framework Application

In my Play + Reactive Mongo application, I'm getting Future[Option[Student]] result and I' trying to match result:

def getStudent(id: String)=Action {
  val futureOfStudent:Future[Option[Student]] = StudentRepository.getStudentById(id)
  val timeoutFuture = play.api.libs.concurrent.Promise.timeout(0,  Duration(3000, MILLISECONDS))
  Async {
    Future.firstCompletedOf(Seq(futureOfStudent, timeoutFuture)).map { 
      case s: Option[Student] => {s match {case Some(s)=>Ok(Json.toJson(s))
                                               case None => NoContent}}
      case i: Int => InternalServerError("Oooppppps!!!")
    }  
  }
} 

Everything works like charm but I'm getting ugly warning on case s: Option[Student] =>

- non-variable type argument model.Student in type pattern 
     Option[modelStudent] is unchecked since it is eliminated by erasure

How can I solve this warning?

I googled it and found some articles:

How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections?

Why does Scala warn about type erasure in the first case but not the second?

but, it did not give me a clue how to solve as part of Play controller.

Please help.

Upvotes: 3

Views: 186

Answers (1)

Dylan
Dylan

Reputation: 13922

The problem with type erasure is that you can no longer use type parameters: Option[Student] at runtime just looks like Option[_]. This leads to problems like:

val opt: Option[Student] = Some(myStudent)
opt match {
  case s: Option[String] => println('problem') // this would happen
  case s: Option[Student] => // this wouldn't get called
}

The easiest approach to solving your problem would probably be something along the lines of...

case s: Option[_] => s match {
  case Some(student: Student) => Ok(Json.toJson(student))
  case _ => NoContent
}

but this doesn't really tackle the root of your problem. The Seq you create contains a Future[Option[Student]] and a Future[Int], so it's likely resolving as a Seq[Future[Any]] (the best common type between Option[Student] and Int), and so your match has to assume that the item is of type Any, which essentially removes the usefulness of the type checker here.

You should adjust the Seq so that it has a better common type. If you used Option[Student] as the return type of your timeout future, it could return None, and the Seq would be a Seq[Future[Option[Student]]]. Then the map could assume you are matching on Option[Student].

Upvotes: 3

Related Questions