object Holder {
opaque type Id <: Int = Int
def apply(a: Int): Id = a
}
val arr: IArray[Holder.Id] = IArray.tabulate(10)(Holder.apply)
val x: Holder.Id = arr(1) // this line does not compile
The error is:
Found: Int
Required: worksheet.Holder.Id
The code starts working if I change IArray back to normal Array.
toSet also does not play well (but it does with normal Array). So in current form, IArray is unusable. Too many quirks.
object Holder {
opaque type Id <: Int = Int
def apply(a: Int): Id = a
}
val arr: IArray[Holder.Id] = IArray.tabulate(10)(Holder.apply)
val x: Set[Holder.Id] = arr.toSet // does not compile
you can fix this with opaque type Id >: Int <: Int = Int,
what’s happening is that because Array is invariant, then Holder.Id is not exactly Int so it wraps in Predef.genericWrapArray.
because IArray is covariant, then IArray[Holder.Id] counts as IArray[Int] so applies IArray.wrapIntArray, and ArraySeq.ofInt requires a lower bound of Int for the type argument to toSet
object Holder {
opaque type Id >: Int <: Int = Int
def apply(a: Int): Id = a
}
val arr: IArray[Holder.Id] = IArray.tabulate(10)(Holder.apply)
val x: Set[Holder.Id] = arr.toSet // ok
Perhaps we should look into downcasting as an improvement, so the conversion will convert IArray[Holder.Id] to (new ArraySeq.OfInt(...)).asInstanceOf[ArraySeq[Holder.Id]].
a slight wrinkle - there could be code out there relying on the result of conversion being exactly ArraySeq.ofInt, but we could bridge that by keeping the present conversions as non-implicit
I guess the choice could have been made to keep it invariant, but that can’t change now.
I would basically make the specialised conversions non-implicit so then it will always use the generic conversion (with generic return type), perhaps we can still shortcut the runtime type test within the conversion method.