Consider if type is existential when calling dealias?
dwijnand opened this issue · comments
Good spot. Yes, semantics of dealias
in 2.11.x aren't quite the same as normalize
in 2.10.x. I'll ask on scala/contributors ...
In that case, perhaps the special casing of typeArgs
is in the same boat: https://github.com/milessabin/shapeless/blob/2e4a784c27cf2d6ed46dc01818adc4497110500e/core/src/main/scala/shapeless/typeable.scala#L361-L362
Yes, that's related IIRC.
More evidence that dealias
(and typeArgs
) needs tweaking with regards to ExistentialType
:
// Doesn't work, bug in macro-compat
// val dealiased = tpe.dealias
val dealiased = tpe match {
case existential: ExistentialType => existential
case other => other.normalize
}
dealiased match {
...
case ExistentialType(quantified, underlying) =>
// Doesn't work, bug in macro-compat
// val tArgs = dealiased.typeArgs
val TypeRef(_, _, tArgs0) = underlying
val tArgs = tArgs0.map { tpe => if(tpe.typeSymbol.asType.isExistential) typeOf[Any] else tpe }
...
For more context, those are taken from trying to migrate the Scala 2.10 variant of Shapeless' TypeableMacros
, and the failure is that the test code in core/src/test/scala/shapeless/typeable.scala
doesn't compile (if I recall correctly the error was "can't find Typeable instance for this type")
[error] /Users/dnw/dev/shapeless-2.10/core/src/test/scala/shapeless/typeable.scala:367: could not find implicit value for parameter castU: shapeless.Typeable[Either[Int, _]]
[error] val cei3 = ei.cast[Either[Int, _]]
[error] ^
[error] /Users/dnw/dev/shapeless-2.10/core/src/test/scala/shapeless/typeable.scala:380: could not find implicit value for parameter castU: shapeless.Typeable[Either[_, String]]
[error] val ces3 = es.cast[Either[_, String]]
[error] ^
[error] two errors found
I tried a bunch of different combinations, both in here and in combination with different .typeArgs implementation.
I have no idea, I've just special-cased the two instances I found:
I don't see a point in continuing to keep this issue open.
I'm going to reopen this because I'd like to take another look. Can you say what you tried as implementations of dealias
and typeArgs
? Did you go as far as copy/pasting the 2.11.x definitions into macro-compat?
👍
I tried different combinations (merges) of possible definitions of Type#dealias
between
val dealiased = tpe match {
case existential: ExistentialType => existential
case other => other.normalize
}
and
def dealias(t: Type) = t match {
case _ if t.takesTypeArgs => t
case _ : RefinedType => t
case _ => t.normalize
}
that @retronym recommended, in combinations with possible definitions of Type#typeArgs
between
def typeArgs: List[Type] = tpe match {
case TypeRef(_, _, args) => args
case _ => Nil
}
and
def typeArgs: List[Type] = tpe match {
case TypeRef(_, _, args) => args.map { tpe => if(tpe.typeSymbol.asType.isExistential) typeOf[Any] else tpe }
case _ => Nil
}
and something somewhere (sorry it was a little while ago) broke in shapeless' build.
Thanks ... I'll try the copy/paste from 2.11.x approach :-)
Fixed in 5bbf257.
Very cool, thank you.
Possibly a bit hasty. Back in shapeless dealias
is looking good, but typeArgs
isn't quite the same.
oh
Done :-)