milessabin / shapeless

Generic programming for Scala

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Witness path-dependent type `T` lose refinement

tribbloid opened this issue · comments

When execution the following code (after successful compilation):

import shapeless.Witness

object Bug1 {

  val w1: Witness.Lt[Int] = Witness(1)
  val v1 = w1.value

  def main(args: Array[String]): Unit = {
    def infer[T](v: T)(implicit ev: WeakTypeTag[T]): WeakTypeTag[T] = ev

    val tag = infer(v1)

    tag.tpe
  }
}

The following error will be triggered:

Exception in thread "main" java.lang.AssertionError: assertion failed: <refinement>
	at scala.reflect.internal.SymbolTable.throwAssertionError(SymbolTable.scala:184)
	at scala.reflect.internal.Symbols$Symbol.completeInfo(Symbols.scala:1525)
	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1514)
	at scala.reflect.runtime.SynchronizedSymbols$$anon$2.scala$reflect$runtime$SynchronizedSymbols$SynchronizedSymbol$$super$info(SynchronizedSymbols.scala:42)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol.$anonfun$info$1(SynchronizedSymbols.scala:158)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol.info(SynchronizedSymbols.scala:149)
	at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol.info$(SynchronizedSymbols.scala:158)
	at scala.reflect.runtime.SynchronizedSymbols$$anon$2.info(SynchronizedSymbols.scala:42)
	at scala.reflect.internal.ReificationSupport$ReificationSupportImpl.select(ReificationSupport.scala:34)
	at scala.reflect.internal.ReificationSupport$ReificationSupportImpl.selectType(ReificationSupport.scala:25)
	at scala.reflect.internal.ReificationSupport$ReificationSupportImpl.selectType(ReificationSupport.scala:23)
...

Indicating that the type refinement of type w1.T is lost.

In contrast the following code (with Witness.Lt[Int] removed) won't have such problem:

import shapeless.Witness

object Bug1 {

  val w1 = Witness(1)
  val v1 = w1.value

  def main(args: Array[String]): Unit = {
    def infer[T](v: T)(implicit ev: WeakTypeTag[T]): WeakTypeTag[T] = ev

    val tag = infer(v1)

    tag.tpe
  }
}

Since Bug1.w1 is a stable path, type resolving should have no difference between 2 cases.

Indicating that the type refinement of type w1.T is lost.

No, this exception means that when runtime reflection works the following assertion fails

https://github.com/scala/scala/blob/2.13.x/src/reflect/scala/reflect/internal/Symbols.scala#L1543

      assert(infos.prev eq null, this.name)

<refinement> is this.name.

@DmytroMitin you are correct on that statement, but this assertion could only have 2 possibilities, either:

  • it shouldn't be there, Symbols.scala has a defect, OR
  • w1.value was assigned the wrong type by the macro.

Which one is it?

Fixed by #1242