Skip to content

Commit 3034f59

Browse files
committed
Optimize asSeenFrom for applied types
... and remove previous optimizations for RefinedTypes and TypeAliases.
1 parent fc83c24 commit 3034f59

File tree

1 file changed

+57
-37
lines changed

1 file changed

+57
-37
lines changed

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,71 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
2222
/** The type `tp` as seen from prefix `pre` and owner `cls`. See the spec
2323
* for what this means.
2424
*/
25-
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol): Type =
26-
new AsSeenFromMap(pre, cls).apply(tp)
27-
28-
/** The TypeMap handling the asSeenFrom */
29-
class AsSeenFromMap(pre: Type, cls: Symbol) extends ApproximatingTypeMap {
25+
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol): Type = tp match {
26+
case tp: NamedType =>
27+
if (tp.symbol.isStatic) tp
28+
else
29+
tp.derivedSelect(asSeenFrom(tp.prefix, pre, cls)) match {
30+
case tp1: TypeArgRef => tp1.underlying.hiBound
31+
case tp1 => tp1
32+
}
33+
case tp: ThisType => toPrefix(tp, pre, cls, tp.cls, 1)
34+
case _: BoundType => tp
35+
case _ => new AsSeenFromMap(pre, cls, 1).mapOver2(tp)
36+
}
3037

31-
def apply(tp: Type): Type = {
38+
/** Map a `C.this` type to the right prefix. If the prefix is unstable, and
39+
* the current variance is <= 0, return a range.
40+
*/
41+
def toPrefix(tp: Type, pre: Type, cls: Symbol, thiscls: ClassSymbol, variance: Int): Type = /*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"toPrefix($pre, $cls, $thiscls)") /*<|<*/ {
42+
if ((pre eq NoType) || (pre eq NoPrefix) || (cls is PackageClass))
43+
tp
44+
else pre match {
45+
case pre: SuperType => toPrefix(tp, pre.thistpe, cls, thiscls, variance)
46+
case _ =>
47+
if (thiscls.derivesFrom(cls) && pre.baseType(thiscls).exists)
48+
if (variance > 0 || isLegalPrefix(pre)) pre
49+
else new AsSeenFromMap(pre, cls, variance).range(pre.bottomType, pre)
50+
else if ((pre.termSymbol is Package) && !(thiscls is Package))
51+
toPrefix(tp, pre.select(nme.PACKAGE), cls, thiscls, variance)
52+
else
53+
toPrefix(tp, pre.baseType(cls).normalizedPrefix, cls.owner, thiscls, variance)
54+
}
55+
}
3256

33-
/** Map a `C.this` type to the right prefix. If the prefix is unstable, and
34-
* the current variance is <= 0, return a range.
35-
*/
36-
def toPrefix(pre: Type, cls: Symbol, thiscls: ClassSymbol): Type = /*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"toPrefix($pre, $cls, $thiscls)") /*<|<*/ {
37-
if ((pre eq NoType) || (pre eq NoPrefix) || (cls is PackageClass))
38-
tp
39-
else pre match {
40-
case pre: SuperType => toPrefix(pre.thistpe, cls, thiscls)
41-
case _ =>
42-
if (thiscls.derivesFrom(cls) && pre.baseType(thiscls).exists)
43-
if (variance <= 0 && !isLegalPrefix(pre)) range(pre.bottomType, pre)
44-
else pre
45-
else if ((pre.termSymbol is Package) && !(thiscls is Package))
46-
toPrefix(pre.select(nme.PACKAGE), cls, thiscls)
47-
else
48-
toPrefix(pre.baseType(cls).normalizedPrefix, cls.owner, thiscls)
49-
}
50-
}
57+
/** The TypeMap handling the asSeenFrom */
58+
class AsSeenFromMap(pre: Type, cls: Symbol, v: Int) extends ApproximatingTypeMap {
59+
variance = v
5160

52-
/*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"asSeen ${tp.show} from (${pre.show}, ${cls.show})", show = true) /*<|<*/ { // !!! DEBUG
53-
// All cases except for ThisType are the same as in Map. Inlined for performance
54-
// TODO: generalize the inlining trick?
61+
def apply(tp: Type): Type =
62+
/*>|> ctx.conditionalTraceIndented(TypeOps.track, s"asSeen ${tp.show} from (${pre.show}, ${cls.show})", show = true) <|<*/ { // !!! DEBUG
5563
tp match {
5664
case tp: NamedType =>
57-
val sym = tp.symbol
58-
if (sym.isStatic) tp
65+
if (tp.symbol.isStatic) tp
5966
else derivedSelect(tp, atVariance(variance max 0)(this(tp.prefix)))
60-
case tp: ThisType =>
61-
toPrefix(pre, cls, tp.cls)
62-
case _: BoundType | NoPrefix =>
63-
tp
64-
case tp: RefinedType => //@!!!
65-
derivedRefinedType(tp, apply(tp.parent), apply(tp.refinedInfo))
66-
case _ =>
67-
mapOver(tp)
67+
case tp: ThisType => toPrefix(tp, pre, cls, tp.cls, variance)
68+
case _: BoundType => tp
69+
case _ => mapOver2(tp)
6870
}
6971
}
72+
73+
override def mapOver2(tp: Type) = tp match {
74+
case tp: AppliedType =>
75+
def mapArgs(args: List[Type], tparams: List[ParamInfo]): List[Type] = args match {
76+
case arg :: otherArgs =>
77+
val arg1 = arg match {
78+
case arg: TypeBounds => this(arg)
79+
case arg => atVariance(variance * tparams.head.paramVariance)(this(arg))
80+
}
81+
val otherArgs1 = mapArgs(otherArgs, tparams.tail)
82+
if ((arg1 eq arg) && (otherArgs1 eq otherArgs)) args
83+
else arg1 :: otherArgs1
84+
case nil =>
85+
nil
86+
}
87+
derivedAppliedType(tp, this(tp.tycon), mapArgs(tp.args, tp.typeParams))
88+
case _ =>
89+
mapOver3(tp)
7090
}
7191

7292
override def reapply(tp: Type) =

0 commit comments

Comments
 (0)