diff --git a/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/dottyreflection/Inspector.scala b/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/dottyreflection/Inspector.scala index 1e98b6e1..4ec16d0e 100644 --- a/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/dottyreflection/Inspector.scala +++ b/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/dottyreflection/Inspector.scala @@ -70,16 +70,17 @@ abstract class Inspector(protected val shift: Int, val context: Queue[Inspector. inspectTypeRepr(a.underlying) case appliedType: AppliedType => - appliedType.args match { + val tycon: TypeRepr = appliedType.tycon._dealiasSimplifiedFull + val args0: List[TypeRepr] = appliedType.args + args0 match { case Nil => - makeNameReferenceFromType(appliedType.tycon) + makeNameReferenceFromType(tycon) case _ => - val symbolVariances = appliedType.tycon.typeSymbol.typeMembers.collect { - case s if s.isTypeParam => - extractVariance(s) + val symbolVariances: List[Variance] = tycon.typeSymbol.declaredTypes.collect { + case s if s.isTypeParam => extractVariance(s) } - val variances = if (symbolVariances.sizeCompare(appliedType.args) < 0) { - appliedType.tycon match { + val variances: List[Variance] = if (symbolVariances.sizeCompare(appliedType.args) < 0) { + tycon match { case typeParamRef: ParamRef => typeParamRef._underlying match { case TypeBounds(_, hi) => @@ -93,9 +94,9 @@ abstract class Inspector(protected val shift: Int, val context: Queue[Inspector. } else { symbolVariances } - val nameRef = makeNameReferenceFromType(appliedType.tycon) - val args = appliedType - .args.iterator + val nameRef = makeNameReferenceFromType(tycon) + val args = args0 + .iterator .zipAll(variances, null.asInstanceOf[TypeRepr], Variance.Invariant) .takeWhile(_._1 != null) .map(next().inspectTypeParam(_, _)).toList diff --git a/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/dottyreflection/ReflectionUtil.scala b/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/dottyreflection/ReflectionUtil.scala index c8ff6671..88378c47 100644 --- a/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/dottyreflection/ReflectionUtil.scala +++ b/izumi-reflect/izumi-reflect/src/main/scala-3/izumi/reflect/dottyreflection/ReflectionUtil.scala @@ -86,6 +86,12 @@ private[dottyreflection] trait ReflectionUtil { this: InspectorBase => import ReflectionUtil.reflectiveUncheckedNonOverloadedSelectable import InternalContext.InternalContext + extension (symbol: Symbol) { + protected final def _info: TypeRepr = { + symbol.asInstanceOf[InternalSymbol].denot(qctx._ctx).info(qctx._ctx) + } + } + extension (typeRef: TypeRef | ParamRef) { protected final def _underlying: TypeRepr = { // This works as a substitution for `TypeRef#underlying` call, @@ -122,7 +128,8 @@ private[dottyreflection] trait ReflectionUtil { this: InspectorBase => protected final def _dealiasSimplifiedFull: TypeRepr = { // val res = typeRepr.dealias.simplified // simplified does everything below functions do, with exception of `_removeTautologicalUnions` for some reason - // All of these would be more useful, if not for forced type simplification on implicit macro - https://github.com/lampepfl/dotty/issues/17544 + // All of these would be more useful, if not for forced type simplification on implicit macro + // - https://github.com/lampepfl/dotty/issues/17544 val res = typeRepr.dealias._removeTautologicalIntersections._removeTautologicalUnions._simplifyMatchCase if (res.asInstanceOf[AnyRef] eq typeRepr.asInstanceOf[AnyRef]) { res @@ -222,6 +229,14 @@ private[dottyreflection] trait ReflectionUtil { this: InspectorBase => def paramVariance(ctx: InternalContext): Flags } + type InternalSymbol = { + def denot(ctx: InternalContext): InternalDenot + } + + type InternalDenot = { + def info(ctx: InternalContext): TypeRepr + } + object InternalContext { opaque type InternalContext = Any } diff --git a/izumi-reflect/izumi-reflect/src/test/scala/izumi/reflect/test/SharedLightTypeTagTest.scala b/izumi-reflect/izumi-reflect/src/test/scala/izumi/reflect/test/SharedLightTypeTagTest.scala index 42000ba6..2ffbdef8 100644 --- a/izumi-reflect/izumi-reflect/src/test/scala/izumi/reflect/test/SharedLightTypeTagTest.scala +++ b/izumi-reflect/izumi-reflect/src/test/scala/izumi/reflect/test/SharedLightTypeTagTest.scala @@ -1,6 +1,6 @@ package izumi.reflect.test -import izumi.reflect.macrortti.LightTypeTagRef.{AbstractReference, AppliedNamedReference, Boundaries, FullReference, NameReference, TypeParam} +import izumi.reflect.macrortti.LightTypeTagRef.{AbstractReference, AppliedNamedReference, Boundaries, FullReference, NameReference, TypeParam, Variance} import izumi.reflect.macrortti._ import scala.collection.immutable.ListSet @@ -488,7 +488,7 @@ abstract class SharedLightTypeTagTest extends TagAssertions { object A extends Base object B extends Base - assertDifferent(LTT[A.Nested.Member], LTT[B.Nested.Member]) + assertDifferent(LTT[A.Nested.Member], LTT[B.Nested.Member]) } "properly dealias and assign prefixes to existential types and wildcards" in { @@ -784,6 +784,38 @@ abstract class SharedLightTypeTagTest extends TagAssertions { assertRepr(`LTT[_]`[S[Unit, *]], "λ %0 → Either[+0,+Unit]") } + "regression test for https://github.com/zio/izumi-reflect/issues/511" in { + class Foo5[-A, B, -C, +DXX, +E] + class Foo10[F[_], +G[_], -H[-_, +_], I, +J[+_, +_], B, -A, -C, +E, +DXX] extends Foo5[A, B, C, DXX, E] + + val tag1 = LTT[Foo5[Int, String, Double, Float, Long]] + + assert(tag1.ref.isInstanceOf[FullReference]) + assert( + tag1.ref.asInstanceOf[FullReference].parameters.map(_.variance) + == List(Variance.Contravariant, Variance.Invariant, Variance.Contravariant, Variance.Covariant, Variance.Covariant) + ) + + val tag2 = LTT[Foo10[Option, List, Function1, Boolean, Either, Int, String, Double, Float, Long]] + + assert(tag2.ref.isInstanceOf[FullReference]) + assert( + tag2.ref.asInstanceOf[FullReference].parameters.map(_.variance) + == List( + Variance.Invariant, + Variance.Covariant, + Variance.Contravariant, + Variance.Invariant, + Variance.Covariant, + Variance.Invariant, + Variance.Contravariant, + Variance.Contravariant, + Variance.Covariant, + Variance.Covariant + ) + ) + } + } }