From 38b2a61e3dba6160292943a481ccf2b85a695ba7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 16 Nov 2014 19:22:21 +0100 Subject: 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. --- src/dotty/tools/dotc/core/TypeOps.scala | 8 +++++++- src/dotty/tools/dotc/core/Types.scala | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'src/dotty/tools/dotc') 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 || -- cgit v1.2.3