Considering the following code:
import scala.reflect.api.Universe
object UnqualifiedTypeTag {
val RuntimeUniverse = scala.reflect.runtime.universe
trait HasUniverse {
val universe: Universe with Singleton
def uType: RuntimeUniverse.TypeTag[universe.type] = implicitly
}
object HasRuntime extends HasUniverse {
override val universe: RuntimeUniverse.type = RuntimeUniverse
}
def main(args: Array[String]): Unit = {
println(HasRuntime.uType)
}
}
Ideally, this part of the program should yield TypeTag[HasRuntime.universe.type], or at least fail its compilation, due to implicitly only able to see universe.type, which is not known at call site. (in contrast, WeakTypeTag[universe.type] should totally work)
Surprisingly, the above program yields TypeTag[HasUniverse.this.universe.type]. This apparently breaks many contracts, namely:
- TypeTag cannot be initialised from abstract types, unlike WeakTypeTag
- TypeTag can always be erased to a Class
What's the purpose of this design, and what contract does TypeTag provide? In addition, is this the reason why ClassTag was supposed to be superseded after Scala 2.11, but instead was kept as-is until now?
You seem to still confuse
implicitly[X]and(implicit x: X)When doing implicit resolution with type parameters, why does val placement matter?
In scala 2, can macro or any language feature be used to rewrite the abstract type reification mechanism in all subclasses? How about scala 3?
SYB `cast` function in Scala
Setting abstract type based on typeclass
There is no implicit resolution in the line
println(HasRuntime.uType). Implicits are resolved in the right hand side of the linedef uType: RuntimeUniverse.TypeTag[universe.type] = implicitly. For implicits, the call site is notHasRuntime.uType, the call site isimplicitly.Simpler example is the following (let's make the code self-contained and remove macros or compiler
TypeTagmagic, keeping ordinary implicits)Even simpler example:
If you want implicits to resolve in the line
println(Child.uType)then add an implicit parameter to the methodOne more option to postpone implicit resolution besides adding an implicit parameter is inlining (with
inlinein Scala 3 or a macro in Scala 2)Why the Scala compiler can provide implicit outside of object, but cannot inside? (answer)
Type parameter for implicit valued method in Scala - Circe
Implicit Json Formatter for value classes in Scala
Here you seem to have one more confusion. The type
universe.typeis not abstract, it's a singleton type inhabited by theval universeoftrait HasUniverse. It'sval universethat is abstract but not its type.https://scala-lang.org/files/archive/spec/2.13/03-types.html