diff options
author | Martin Odersky <odersky@gmail.com> | 2014-11-16 19:22:21 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-11-24 14:54:58 +0100 |
commit | 38b2a61e3dba6160292943a481ccf2b85a695ba7 (patch) | |
tree | 401db93fdf090106fab48a5b76eccadad9a40572 /src/dotty/tools/dotc/core/Types.scala | |
parent | 779afd2f65f967ec5af1ac5ec7464ad5851852ad (diff) | |
download | dotty-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.scala | 33 |
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 || |