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