aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala8
-rw-r--r--src/dotty/tools/dotc/core/Types.scala33
2 files changed, 40 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index 7a853ae12..1ef997684 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -56,7 +56,13 @@ trait TypeOps { this: Context =>
final def simplify(tp: Type, theMap: SimplifyMap): Type = tp match {
case tp: NamedType =>
if (tp.symbol.isStatic) tp
- else tp.derivedSelect(simplify(tp.prefix, theMap))
+ else tp.derivedSelect(simplify(tp.prefix, theMap)) match {
+ case tp1: NamedType if tp1.denotationIsCurrent =>
+ val tp2 = tp1.reduceProjection
+ //if (tp2 ne tp1) println(i"simplified $tp1 -> $tp2")
+ tp2
+ case tp1 => tp1
+ }
case tp: PolyParam =>
typerState.constraint.typeVarOfParam(tp) orElse tp
case _: ThisType | _: BoundType | NoPrefix =>
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 ||