Skip to content

Commit 0dbce7d

Browse files
committed
Improve simplifications of type projections.
An example where this helps: Previously, the private value `mnemonics` in Coder.scala was fof the form Lambda$IP { ... } # Apply It now simplifies to a Map[...] type.
1 parent 4cb35ef commit 0dbce7d

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ trait TypeOps { this: Context =>
5656
final def simplify(tp: Type, theMap: SimplifyMap): Type = tp match {
5757
case tp: NamedType =>
5858
if (tp.symbol.isStatic) tp
59-
else tp.derivedSelect(simplify(tp.prefix, theMap))
59+
else tp.derivedSelect(simplify(tp.prefix, theMap)) match {
60+
case tp1: NamedType if tp1.denotationIsCurrent =>
61+
val tp2 = tp1.reduceProjection
62+
//if (tp2 ne tp1) println(i"simplified $tp1 -> $tp2")
63+
tp2
64+
case tp1 => tp1
65+
}
6066
case tp: PolyParam =>
6167
typerState.constraint.typeVarOfParam(tp) orElse tp
6268
case _: ThisType | _: BoundType | NoPrefix =>

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,39 @@ object Types {
12791279
if (name.isInheritedName) prefix.nonPrivateMember(name.revertInherited)
12801280
else prefix.member(name)
12811281

1282+
/** Reduce a type-ref `T { X = U; ... } # X` to `U`
1283+
* provided `U` does not refer with a RefinedThis to the
1284+
* refinement type `T { X = U; ... }`.
1285+
*/
1286+
def reduceProjection(implicit ctx: Context) =
1287+
if (projectsRefinement(prefix))
1288+
info match {
1289+
case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi
1290+
case _ => this
1291+
}
1292+
else this
1293+
1294+
private def projectsRefinement(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
1295+
case tp: RefinedType => (tp.refinedName eq name) || projectsRefinement(tp.parent)
1296+
case _ => false
1297+
}
1298+
1299+
private def dependsOnRefinedThis(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
1300+
case tp @ TypeRef(RefinedThis(rt), _) if rt refines prefix =>
1301+
tp.info match {
1302+
case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi)
1303+
case _ => true
1304+
}
1305+
case RefinedThis(rt) => rt refines prefix
1306+
case tp: NamedType =>
1307+
!tp.symbol.isStatic && dependsOnRefinedThis(tp.prefix)
1308+
case tp: RefinedType => dependsOnRefinedThis(tp.refinedInfo) || dependsOnRefinedThis(tp.parent)
1309+
case tp: TypeBounds => dependsOnRefinedThis(tp.lo) || dependsOnRefinedThis(tp.hi)
1310+
case tp: AnnotatedType => dependsOnRefinedThis(tp.underlying)
1311+
case tp: AndOrType => dependsOnRefinedThis(tp.tp1) || dependsOnRefinedThis(tp.tp2)
1312+
case _ => false
1313+
}
1314+
12821315
def symbol(implicit ctx: Context): Symbol = {
12831316
val now = ctx.period
12841317
if (checkedPeriod == now ||

0 commit comments

Comments
 (0)