Skip to content

Commit 45bfa08

Browse files
committed
Make applications inside ranges respect variance
A Range, if it survives, will always lead to a situation where the upper bound appears in a covariant position in the result, and the lower bound appears in a contravariant position. Hence, when we apply a type map to the argument in a range we should take this into account. Fixes a previous failure in t2435.scala and dependent-extractors.scala.
1 parent 416fadc commit 45bfa08

File tree

4 files changed

+29
-8
lines changed

4 files changed

+29
-8
lines changed

compiler/src/dotty/tools/dotc/core/TypeOps.scala

+5-3
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,11 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
132132

133133
/** Approximate a type `tp` with a type that does not contain skolem types. */
134134
object deskolemize extends ApproximatingTypeMap {
135-
def apply(tp: Type) = tp match {
136-
case tp: SkolemType => range(hi = apply(tp.info))
137-
case _ => mapOver(tp)
135+
def apply(tp: Type) = /*ctx.traceIndented(i"deskolemize($tp) at $variance", show = true)*/ {
136+
tp match {
137+
case tp: SkolemType => range(hi = atVariance(1)(apply(tp.info)))
138+
case _ => mapOver(tp)
139+
}
138140
}
139141
}
140142

compiler/src/dotty/tools/dotc/core/Types.scala

+21-3
Original file line numberDiff line numberDiff line change
@@ -3888,6 +3888,9 @@ object Types {
38883888
case class Range(lo: Type, hi: Type) extends UncachedGroundType {
38893889
assert(!lo.isInstanceOf[Range])
38903890
assert(!hi.isInstanceOf[Range])
3891+
3892+
override def toText(printer: Printer): Text =
3893+
lo.toText(printer) ~ ".." ~ hi.toText(printer)
38913894
}
38923895

38933896
/** A type map that approximates TypeBounds types depending on
@@ -3922,14 +3925,23 @@ object Types {
39223925
case _ => tp
39233926
}
39243927

3928+
def atVariance[T](v: Int)(op: => T): T = {
3929+
val saved = variance
3930+
variance = v
3931+
try op finally variance = saved
3932+
}
3933+
39253934
override protected def derivedSelect(tp: NamedType, pre: Type) =
39263935
if (pre eq tp.prefix) tp
39273936
else pre match {
39283937
case Range(preLo, preHi) =>
39293938
tp.info match {
3930-
case TypeAlias(alias) => apply(alias)
3931-
case TypeBounds(lo, hi) => range(apply(lo), apply(hi))
3932-
case _ => range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
3939+
case TypeAlias(alias) =>
3940+
apply(alias)
3941+
case TypeBounds(lo, hi) =>
3942+
range(atVariance(-1)(apply(lo)), atVariance(1)(apply(hi)))
3943+
case _ =>
3944+
range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
39333945
}
39343946
case _ => tp.derivedSelect(pre)
39353947
}
@@ -3947,23 +3959,27 @@ object Types {
39473959
tp.derivedRefinedType(parent, tp.refinedName, rangeToBounds(info))
39483960
}
39493961
}
3962+
39503963
override protected def derivedRecType(tp: RecType, parent: Type) =
39513964
parent match {
39523965
case Range(lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
39533966
case _ => tp.rebind(parent)
39543967
}
3968+
39553969
override protected def derivedTypeAlias(tp: TypeAlias, alias: Type) =
39563970
alias match {
39573971
case Range(lo, hi) =>
39583972
if (variance > 0) TypeBounds(lo, hi)
39593973
else range(TypeAlias(lo), TypeAlias(hi))
39603974
case _ => tp.derivedTypeAlias(alias)
39613975
}
3976+
39623977
override protected def derivedTypeBounds(tp: TypeBounds, lo: Type, hi: Type) =
39633978
if (isRange(lo) || isRange(hi))
39643979
if (variance > 0) TypeBounds(loBound(lo), hiBound(hi))
39653980
else range(TypeBounds(hiBound(lo), loBound(hi)), TypeBounds(loBound(lo), hiBound(hi)))
39663981
else tp.derivedTypeBounds(lo, hi)
3982+
39673983
override protected def derivedSuperType(tp: SuperType, thistp: Type, supertp: Type) =
39683984
if (isRange(thistp) || isRange(supertp)) range()
39693985
else tp.derivedSuperType(thistp, supertp)
@@ -4003,6 +4019,7 @@ object Types {
40034019
if (tp.isAnd) range(loBound(tp1) & loBound(tp2), hiBound(tp1) & hiBound(tp2))
40044020
else range(loBound(tp1) | loBound(tp2), hiBound(tp1) | hiBound(tp2))
40054021
else tp.derivedAndOrType(tp1, tp2)
4022+
40064023
override protected def derivedAnnotatedType(tp: AnnotatedType, underlying: Type, annot: Annotation) =
40074024
underlying match {
40084025
case Range(lo, hi) =>
@@ -4014,6 +4031,7 @@ object Types {
40144031
override protected def derivedWildcardType(tp: WildcardType, bounds: Type) = {
40154032
tp.derivedWildcardType(rangeToBounds(bounds))
40164033
}
4034+
40174035
override protected def derivedClassInfo(tp: ClassInfo, pre: Type): Type = {
40184036
assert(!pre.isInstanceOf[Range])
40194037
tp.derivedClassInfo(pre)

tests/pos/dependent-extractors.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ object Test {
1010
val y1: Int = y
1111

1212
val z = (c: Any) match { case X(y) => y }
13-
// val z1: C#T = z // error: z has type Any TODO: find out why
13+
val z1: C#T = z // error: z has type Any TODO: find out why
1414
}

tests/pos/t2435.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ object Test {
2323
val a2 = a1.chain("a")
2424

2525
println("\nDoesn't compile:")
26-
val a = FNil.chain("a").chain("a").chain("a")
26+
val a3 = FNil.chain("a").chain("a").chain("a")
27+
val a4: FConstant[_ <: FConstant[_ <: FConstant[FNil.type]]] = a3
2728
}

0 commit comments

Comments
 (0)