Manu Chadha
Manu Chadha

Reputation: 16723

REPL warning on using structural types

Why REPL gives warning on using structural types? Are structural types unsafe to use?

scala> def test(st: { def close():Unit})
     | = st.close()
<console>:12: warning: reflective access of structural type member method close should be enabled
by making the implicit value scala.language.reflectiveCalls visible.
This can be achieved by adding the import clause 'import scala.language.reflectiveCalls'
or by setting the compiler option -language:reflectiveCalls.
See the Scaladoc for value scala.language.reflectiveCalls for a discussion
why the feature should be explicitly enabled.
       = st.close()
            ^
test: (st: AnyRef{def close(): Unit})Unit

Upvotes: 0

Views: 144

Answers (2)

SergGr
SergGr

Reputation: 23788

I would like to put another point of view than Silvio Mayolo's answer.

Fundamentally the important thing here is that Scala is compiled into a JVM rather than some Scala-specific target platform. This means that many features that exist in Scala are not supported out of the box by the target platform (JVM) and they have to be somehow simulated by the compiler. One of such features is structural types and it is implemented using reflection. And using reflection introduces a bunch of potential issues that are mentioned in Silvio's answer. Thus compiler developers want to make sure that you understand possible drawbacks and still want to use this feature by enforcing either explicit import, compiler configuration or warning.

As for alternatives in your case you may use java.lang.AutoCloseable instead of your structural type and it will probably cover most of your cases.

Another alternative is to use implicit parameter and type class idea:

trait CloseableTC[A] {
  def close(closeable: A): Unit
}


object CloseableTC {
  implicit val javaCloseable: CloseableTC[java.lang.AutoCloseable] = new CloseableTC[java.lang.AutoCloseable] {
    override def close(closeable: AutoCloseable): Unit = closeable.close()
  }

  // add here more implicits for other classes with .close()
}

def testTC[A](a: A)(implicit closeableTC: CloseableTC[A]) = closeableTC.close(a)

import CloseableTC._

Upvotes: 1

Silvio Mayolo
Silvio Mayolo

Reputation: 70277

The warning suggests viewing the Scaladoc page, which says

Why control it? Reflection is not available on all platforms. Popular tools such as ProGuard have problems dealing with it. Even where reflection is available, reflective dispatch can lead to surprising performance degradations.

Source

To make the warning go away, simply add import scala.language.reflectiveCalls to the top of your file to indicate that, yes, you do in fact intend to use this language feature.

Upvotes: 2

Related Questions