Skip to content

Commit 4e3620e

Browse files
committed
Optionally rewrite projections.
1 parent 13fc1ff commit 4e3620e

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/dotty/tools/dotc/config/Config.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,15 @@ object Config {
8787
/** Check that certain types cannot be created in erasedTypes phases */
8888
final val checkUnerased = true
8989

90+
/** In `derivedSelect`, rewrite
91+
*
92+
* (S & T)#A --> S#A & T#A
93+
* (S | T)#A --> S#A | T#A
94+
*
95+
* Not sure whether this is useful. Preliminary measurements show a slowdown of about
96+
* 7% for the build when this option is enabled.
97+
*/
98+
final val splitProjections = false
9099

91100
/** Initial size of superId table */
92101
final val InitialSuperIdsSize = 4096

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,18 +1533,48 @@ object Types {
15331533
ctx.underlyingRecursions -= 1
15341534
}
15351535

1536+
/** A selection of the same kind, but with potentially a differet prefix.
1537+
* The following normalizations are performed for type selections T#A:
1538+
*
1539+
* 1. If Config.splitProjections is true:
1540+
*
1541+
* (S & T)#A --> S#A & T#A
1542+
* (S | T)#A --> S#A | T#A
1543+
*
1544+
* 2. If A is bound to an alias `= B` in T
1545+
*
1546+
* T#A --> B
1547+
*/
15361548
def derivedSelect(prefix: Type)(implicit ctx: Context): Type =
15371549
if (prefix eq this.prefix) this
15381550
else {
1551+
if (Config.splitProjections && isType)
1552+
prefix match {
1553+
case prefix: AndType =>
1554+
def isMissing(tp: Type) = tp match {
1555+
case tp: TypeRef => !tp.info.exists
1556+
case _ => false
1557+
}
1558+
val derived1 = derivedSelect(prefix.tp1)
1559+
val derived2 = derivedSelect(prefix.tp2)
1560+
return (
1561+
if (isMissing(derived1)) derived2
1562+
else if (isMissing(derived2)) derived1
1563+
else prefix.derivedAndType(derived1, derived2))
1564+
case prefix: OrType =>
1565+
val derived1 = derivedSelect(prefix.tp1)
1566+
val derived2 = derivedSelect(prefix.tp2)
1567+
return prefix.derivedOrType(derived1, derived2)
1568+
case _ =>
1569+
}
15391570
val res = prefix.lookupRefined(name)
15401571
if (res.exists) res
15411572
else if (name == tpnme.hkApply && prefix.classNotLambda) {
15421573
// After substitution we might end up with a type like
15431574
// `C { type hk$0 = T0; ...; type hk$n = Tn } # $Apply`
15441575
// where C is a class. In that case we eta expand `C`.
15451576
derivedSelect(prefix.EtaExpandCore(this.prefix.typeConstructor.typeParams))
1546-
}
1547-
else newLikeThis(prefix)
1577+
} else newLikeThis(prefix)
15481578
}
15491579

15501580
/** Create a NamedType of the same kind as this type, but with a new prefix.

0 commit comments

Comments
 (0)