aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-11-16 19:22:21 +0100
committerMartin Odersky <odersky@gmail.com>2014-11-24 14:54:58 +0100
commit38b2a61e3dba6160292943a481ccf2b85a695ba7 (patch)
tree401db93fdf090106fab48a5b76eccadad9a40572 /src/dotty/tools/dotc/core/Types.scala
parent779afd2f65f967ec5af1ac5ec7464ad5851852ad (diff)
downloaddotty-38b2a61e3dba6160292943a481ccf2b85a695ba7.tar.gz
dotty-38b2a61e3dba6160292943a481ccf2b85a695ba7.tar.bz2
dotty-38b2a61e3dba6160292943a481ccf2b85a695ba7.zip
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.
Diffstat (limited to 'src/dotty/tools/dotc/core/Types.scala')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 2997e9e77..333252010 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1309,6 +1309,39 @@ object Types {
if (name.isInheritedName) prefix.nonPrivateMember(name.revertInherited)
else prefix.member(name)
+ /** Reduce a type-ref `T { X = U; ... } # X` to `U`
+ * provided `U` does not refer with a RefinedThis to the
+ * refinement type `T { X = U; ... }`.
+ */
+ def reduceProjection(implicit ctx: Context) =
+ if (projectsRefinement(prefix))
+ info match {
+ case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi
+ case _ => this
+ }
+ else this
+
+ private def projectsRefinement(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
+ case tp: RefinedType => (tp.refinedName eq name) || projectsRefinement(tp.parent)
+ case _ => false
+ }
+
+ private def dependsOnRefinedThis(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
+ case tp @ TypeRef(RefinedThis(rt), _) if rt refines prefix =>
+ tp.info match {
+ case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi)
+ case _ => true
+ }
+ case RefinedThis(rt) => rt refines prefix
+ case tp: NamedType =>
+ !tp.symbol.isStatic && dependsOnRefinedThis(tp.prefix)
+ case tp: RefinedType => dependsOnRefinedThis(tp.refinedInfo) || dependsOnRefinedThis(tp.parent)
+ case tp: TypeBounds => dependsOnRefinedThis(tp.lo) || dependsOnRefinedThis(tp.hi)
+ case tp: AnnotatedType => dependsOnRefinedThis(tp.underlying)
+ case tp: AndOrType => dependsOnRefinedThis(tp.tp1) || dependsOnRefinedThis(tp.tp2)
+ case _ => false
+ }
+
def symbol(implicit ctx: Context): Symbol = {
val now = ctx.period
if (checkedPeriod == now ||