Skip to content

Commit

Permalink
Fix #511 use declaredTypes instead of typeMembers to extract variance…
Browse files Browse the repository at this point in the history
… of type parameters
  • Loading branch information
neko-kai committed Jan 30, 2025
1 parent d488e5f commit cb63bf6
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
)
)
}

}

}

0 comments on commit cb63bf6

Please sign in to comment.