diff options
author | Martin Odersky <odersky@gmail.com> | 2015-07-16 12:14:33 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-09-18 18:05:15 +0200 |
commit | 8c6b70912984e546f16064817446aea3f3863653 (patch) | |
tree | e56e4617073886d9d99bcf88ccc25100f140ec1a /src | |
parent | c28f023c0eb35be14c0e649c14ad10b00603e615 (diff) | |
download | dotty-8c6b70912984e546f16064817446aea3f3863653.tar.gz dotty-8c6b70912984e546f16064817446aea3f3863653.tar.bz2 dotty-8c6b70912984e546f16064817446aea3f3863653.zip |
Add EtaReduce method.
EtaReduce will be used to keep applications on eta expanded methods small.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index a97441681..9837b39b1 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -538,6 +538,7 @@ class TypeApplications(val self: Type) extends AnyVal { def EtaExpand(implicit ctx: Context): Type = { val tparams = typeParams self.appliedTo(tparams map (_.typeRef)).LambdaAbstract(tparams) + //.ensuring(res => res.EtaReduce =:= self, s"res = $res, core = ${res.EtaReduce}, self = $self, hc = ${res.hashCode}") } /** Eta expand if `bound` is a type lambda */ @@ -545,6 +546,38 @@ class TypeApplications(val self: Type) extends AnyVal { if (bound.isLambda && self.typeSymbol.isClass && typeParams.nonEmpty && !isLambda) EtaExpand else self + /** If `self` is an eta expansion of type T, return T, otherwise NoType */ + def EtaReduce(implicit ctx: Context): Type = { + def etaCore(tp: Type, tparams: List[Symbol]): Type = tparams match { + case Nil => tp + case tparam :: otherParams => + tp match { + case tp: RefinedType => + tp.refinedInfo match { + case TypeAlias(TypeRef(RefinedThis(rt), rname)) // TODO: Drop once hk applications have been updated + if (rname == tparam.name) && (rt eq self) => + etaCore(tp.parent, otherParams) + case TypeRef(TypeAlias(TypeRef(RefinedThis(rt), rname)), tpnme.Apply) + if (rname == tparam.name) && (rt eq self) => + etaCore(tp.parent, otherParams) + case _ => + NoType + } + case _ => + NoType + } + } + self match { + case self @ RefinedType(parent, tpnme.Apply) => + val lc = parent.LambdaClass(forcing = false) + self.refinedInfo match { + case TypeAlias(alias) if lc.exists => etaCore(alias, lc.typeParams.reverse) + case _ => NoType + } + case _ => NoType + } + } + /** Test whether this type has a base type of the form `B[T1, ..., Bn]` where * the type parameters of `B` match one-by-one the variances of `tparams`, * and where the lambda abstracted type |