Skip to content

Commit cad0ea7

Browse files
committed
Revise ApproximatingTypeMap
1 parent a9cbedb commit cad0ea7

File tree

1 file changed

+83
-38
lines changed

1 file changed

+83
-38
lines changed

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

Lines changed: 83 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,10 @@ object Types {
281281
}
282282

283283
/** Is this an alias TypeBounds? */
284-
def isAlias: Boolean = this.isInstanceOf[TypeAlias]
284+
final def isAlias: Boolean = this.isInstanceOf[TypeAlias]
285+
286+
/** Is this a non-alias TypeBounds? */
287+
final def isRealTypeBounds = this.isInstanceOf[TypeBounds] && !isAlias
285288

286289
// ----- Higher-order combinators -----------------------------------
287290

@@ -1226,18 +1229,6 @@ object Types {
12261229
case _ => TypeAlias(this)
12271230
}
12281231

1229-
/** The lower bound of a TypeBounds type, the type itself otherwise */
1230-
def loBound = this match {
1231-
case tp: TypeBounds => tp.lo
1232-
case _ => this
1233-
}
1234-
1235-
/** The upper bound of a TypeBounds type, the type itself otherwise */
1236-
def hiBound = this match {
1237-
case tp: TypeBounds => tp.hi
1238-
case _ => this
1239-
}
1240-
12411232
/** The type parameter with given `name`. This tries first `decls`
12421233
* in order not to provoke a cycle by forcing the info. If that yields
12431234
* no symbol it tries `member` as an alternative.
@@ -3733,16 +3724,15 @@ object Types {
37333724
case tp: NamedType =>
37343725
if (stopAtStatic && tp.symbol.isStatic) tp
37353726
else {
3736-
val prefix1 = tp.info match {
3737-
case info: TypeBounds if !info.isAlias =>
3727+
val prefix1 =
3728+
if (tp.info.isRealTypeBounds) {
37383729
// prefix of an abstract type selection is non-variant, since a path
37393730
// cannot be legally widened to its underlying type, or any supertype.
37403731
val saved = variance
37413732
variance = 0
37423733
try this(tp.prefix) finally variance = saved
3743-
case _ =>
3744-
this(tp.prefix)
3745-
}
3734+
}
3735+
else this(tp.prefix)
37463736
derivedSelect(tp, prefix1)
37473737
}
37483738
case _: ThisType
@@ -3872,6 +3862,11 @@ object Types {
38723862
def apply(tp: Type) = tp
38733863
}
38743864

3865+
case class Range(lo: Type, hi: Type) extends UncachedGroundType {
3866+
assert(!lo.isInstanceOf[Range])
3867+
assert(!hi.isInstanceOf[Range])
3868+
}
3869+
38753870
/** A type map that approximates TypeBounds types depending on
38763871
* variance.
38773872
*
@@ -3880,74 +3875,124 @@ object Types {
38803875
* variance = 0 : propagate bounds to next outer level
38813876
*/
38823877
abstract class ApproximatingTypeMap(implicit ctx: Context) extends TypeMap { thisMap =>
3878+
38833879
def range(lo: Type = defn.NothingType, hi: Type = defn.AnyType) =
38843880
if (variance > 0) hi
38853881
else if (variance < 0) lo
3886-
else TypeBounds(lo.loBound, hi.hiBound)
3882+
else Range(loBound(lo), hiBound(hi))
3883+
3884+
def isRange(tp: Type) = tp.isInstanceOf[Range]
3885+
3886+
def loBound(tp: Type) = tp match {
3887+
case tp: Range => tp.lo
3888+
case _ => tp
3889+
}
3890+
3891+
/** The upper bound of a TypeBounds type, the type itself otherwise */
3892+
def hiBound(tp: Type) = tp match {
3893+
case tp: Range => tp.hi
3894+
case _ => tp
3895+
}
3896+
3897+
def rangeToBounds(tp: Type) = tp match {
3898+
case Range(lo, hi) => TypeBounds(lo, hi)
3899+
case _ => tp
3900+
}
38873901

38883902
override protected def derivedSelect(tp: NamedType, pre: Type) =
38893903
if (pre eq tp.prefix) tp
38903904
else pre match {
3891-
case TypeBounds(preLo, preHi) =>
3905+
case Range(preLo, preHi) =>
38923906
tp.info match {
38933907
case TypeAlias(alias) => apply(alias)
3894-
case info @ TypeBounds(lo, hi) => apply(range(lo, hi))
3908+
case TypeBounds(lo, hi) => range(apply(lo), apply(hi))
38953909
case _ => range(tp.derivedSelect(preLo), tp.derivedSelect(preHi))
38963910
}
38973911
case _ => tp.derivedSelect(pre)
38983912
}
3913+
38993914
override protected def derivedRefinedType(tp: RefinedType, parent: Type, info: Type) =
39003915
parent match {
3901-
case TypeBounds(parentLo, parentHi) =>
3916+
case Range(parentLo, parentHi) =>
39023917
range(derivedRefinedType(tp, parentLo, info), derivedRefinedType(tp, parentHi, info))
39033918
case _ =>
39043919
if (parent.isBottomType) parent
39053920
else info match {
3906-
case TypeBounds(infoLo, infoHi) if tp.refinedName.isTermName =>
3921+
case Range(infoLo, infoHi) if tp.refinedName.isTermName || variance <= 0 =>
39073922
range(derivedRefinedType(tp, parent, infoLo), derivedRefinedType(tp, parent, infoHi))
39083923
case _ =>
3909-
tp.derivedRefinedType(parent, tp.refinedName, info)
3924+
tp.derivedRefinedType(parent, tp.refinedName, rangeToBounds(info))
39103925
}
39113926
}
39123927
override protected def derivedRecType(tp: RecType, parent: Type) =
39133928
parent match {
3914-
case TypeBounds(lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
3929+
case Range(lo, hi) => range(tp.rebind(lo), tp.rebind(hi))
39153930
case _ => tp.rebind(parent)
39163931
}
39173932
override protected def derivedTypeAlias(tp: TypeAlias, alias: Type) =
39183933
alias match {
3919-
case bounds: TypeBounds => bounds
3934+
case Range(lo, hi) =>
3935+
if (variance > 0) TypeBounds(lo, hi)
3936+
else range(TypeAlias(lo), TypeAlias(hi))
39203937
case _ => tp.derivedTypeAlias(alias)
39213938
}
39223939
override protected def derivedTypeBounds(tp: TypeBounds, lo: Type, hi: Type) =
3923-
if ((lo eq tp.lo) && (hi eq tp.hi)) tp else range(lo, hi)
3940+
if (isRange(lo) || isRange(hi))
3941+
if (variance > 0) TypeBounds(loBound(lo), hiBound(hi))
3942+
else range(TypeBounds(hiBound(lo), loBound(hi)), TypeBounds(loBound(lo), hiBound(hi)))
3943+
else tp.derivedTypeBounds(lo, hi)
39243944
override protected def derivedSuperType(tp: SuperType, thistp: Type, supertp: Type) =
3925-
if (thistp.isInstanceOf[TypeBounds] || supertp.isInstanceOf[TypeBounds]) range()
3945+
if (isRange(thistp) || isRange(supertp)) range()
39263946
else tp.derivedSuperType(thistp, supertp)
3947+
39273948
override protected def derivedAppliedType(tp: HKApply, tycon: Type, args: List[Type]): Type =
39283949
tycon match {
3929-
case TypeBounds(tyconLo, tyconHi) =>
3930-
range(tp.derivedAppliedType(tyconLo, args), tp.derivedAppliedType(tyconHi, args))
3950+
case Range(tyconLo, tyconHi) =>
3951+
range(derivedAppliedType(tp, tyconLo, args), derivedAppliedType(tp, tyconHi, args))
39313952
case _ =>
3932-
tp.derivedAppliedType(tycon, args)
3953+
if (args.exists(isRange))
3954+
if (variance > 0) tp.derivedAppliedType(tycon, args.map(rangeToBounds))
3955+
else {
3956+
val loBuf, hiBuf = new mutable.ListBuffer[Type]
3957+
def distributeArgs(args: List[Type], tparams: List[ParamInfo]): Boolean = args match {
3958+
case Range(lo, hi) :: args1 =>
3959+
val v = tparams.head.paramVariance
3960+
if (v == 0) false
3961+
else if (v > 0) { loBuf += lo; hiBuf += hi }
3962+
else { loBuf += hi; hiBuf += lo }
3963+
distributeArgs(args1, tparams.tail)
3964+
case arg :: args1 =>
3965+
loBuf += arg; hiBuf += arg
3966+
distributeArgs(args1, tparams.tail)
3967+
case nil =>
3968+
true
3969+
}
3970+
if (distributeArgs(args, tp.typeParams))
3971+
range(tp.derivedAppliedType(tycon, loBuf.toList),
3972+
tp.derivedAppliedType(tycon, hiBuf.toList))
3973+
else range()
3974+
}
3975+
else tp.derivedAppliedType(tycon, args)
39333976
}
3977+
39343978
override protected def derivedAndOrType(tp: AndOrType, tp1: Type, tp2: Type) =
3935-
if (tp1.isInstanceOf[TypeBounds] || tp2.isInstanceOf[TypeBounds])
3936-
if (tp.isAnd) range(tp1.loBound & tp2.loBound, tp1.hiBound | tp1.hiBound)
3937-
else range(tp1.loBound | tp2.loBound, tp1.hiBound & tp1.hiBound)
3979+
if (tp1.isInstanceOf[Range] || tp2.isInstanceOf[Range])
3980+
if (tp.isAnd) range(loBound(tp1) & loBound(tp2), hiBound(tp1) & hiBound(tp2))
3981+
else range(loBound(tp1) | loBound(tp2), hiBound(tp1) | hiBound(tp2))
39383982
else tp.derivedAndOrType(tp1, tp2)
39393983
override protected def derivedAnnotatedType(tp: AnnotatedType, underlying: Type, annot: Annotation) =
39403984
underlying match {
3941-
case TypeBounds(lo, hi) =>
3985+
case Range(lo, hi) =>
39423986
range(tp.derivedAnnotatedType(lo, annot), tp.derivedAnnotatedType(hi, annot))
39433987
case _ =>
39443988
if (underlying.isBottomType) underlying
39453989
else tp.derivedAnnotatedType(underlying, annot)
39463990
}
3947-
override protected def derivedWildcardType(tp: WildcardType, bounds: Type) =
3948-
tp.derivedWildcardType(bounds)
3991+
override protected def derivedWildcardType(tp: WildcardType, bounds: Type) = {
3992+
tp.derivedWildcardType(rangeToBounds(bounds))
3993+
}
39493994
override protected def derivedClassInfo(tp: ClassInfo, pre: Type): Type = {
3950-
assert(!pre.isInstanceOf[TypeBounds])
3995+
assert(!pre.isInstanceOf[Range])
39513996
tp.derivedClassInfo(pre)
39523997
}
39533998
}

0 commit comments

Comments
 (0)