1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package dotty.tools.dotc
package transform
import core._
import Symbols._, Types._, Contexts._, SymDenotations._, DenotTransformers._, Flags._
import util.Positions._
import SymUtils._
import StdNames._, NameOps._
class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx: Context) {
import ast.tpd._
val superCls: Symbol = cls.superClass
val mixins: List[ClassSymbol] = cls.mixins
def implementation(member: TermSymbol): TermSymbol = {
val res = member.copy(
owner = cls,
name = member.name.stripScala2LocalSuffix,
flags = member.flags &~ Deferred,
info = cls.thisType.memberInfo(member)).enteredAfter(thisTransform).asTerm
res.addAnnotations(member.annotations)
res
}
def superRef(target: Symbol, pos: Position = cls.pos): Tree = {
val sup = if (target.isConstructor && !target.owner.is(Trait))
Super(This(cls), tpnme.EMPTY, true)
else
Super(This(cls), target.owner.name.asTypeName, false, target.owner)
//println(i"super ref $target on $sup")
ast.untpd.Select(sup.withPos(pos), target.name)
.withType(NamedType.withFixedSym(sup.tpe, target))
//sup.select(target)
}
/** Is `sym` a member of implementing class `cls`?
* The test is performed at phase `thisTransform`.
*/
def isCurrent(sym: Symbol) =
ctx.atPhase(thisTransform) { implicit ctx =>
cls.info.member(sym.name).hasAltWith(_.symbol == sym)
// this is a hot spot, where we spend several seconds while compiling stdlib
// unfortunately it will discard and recompute all the member chaches,
// both making itself slow and slowing down anything that runs after it
// because resolveSuper uses hacks with explicit adding to scopes through .enter
// this cannot be fixed by a smarter caching strategy. With current implementation
// we HAVE to discard caches here for correctness
}
/** Does `method` need a forwarder to in class `cls`
* Method needs a forwarder in those cases:
* - there's a class defining a method with same signature
* - there are multiple traits defining method with same signature
*/
def needsForwarder(meth: Symbol): Boolean = {
lazy val competingMethods = competingMethodsIterator(meth).toList
def needsDisambiguation = competingMethods.exists(x=> !(x is Deferred)) // multiple implementations are available
def hasNonInterfaceDefinition = competingMethods.exists(!_.owner.is(Trait)) // there is a definition originating from class
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
(meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition ) &&
isCurrent(meth)
}
/** Get `sym` of the method that needs a forwarder
* Method needs a forwarder in those cases:
* - there is a trait that defines a primitive version of implemented polymorphic method.
* - there is a trait that defines a polymorphic version of implemented primitive method.
*/
def needsPrimitiveForwarderTo(meth: Symbol): Option[Symbol] = {
def hasPrimitiveMissMatch(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
case (tp1: MethodicType, tp2: MethodicType) =>
hasPrimitiveMissMatch(tp1.resultType, tp2.resultType) ||
tp1.paramInfoss.flatten.zip(tp1.paramInfoss.flatten).exists(args => hasPrimitiveMissMatch(args._1, args._2))
case _ =>
def isPrimitiveOrValueClass(sym: Symbol): Boolean = sym.isPrimitiveValueClass || sym.isValueClass
isPrimitiveOrValueClass(tp1.typeSymbol) ^ isPrimitiveOrValueClass(tp2.typeSymbol)
}
def needsPrimitiveForwarder(m: Symbol): Boolean =
m.owner != cls && !m.is(Deferred) && hasPrimitiveMissMatch(meth.info, m.info)
if (!meth.is(Method | Deferred, butNot = PrivateOrAccessor) || meth.overriddenSymbol(cls).exists || needsForwarder(meth)) None
else competingMethodsIterator(meth).find(needsPrimitiveForwarder)
}
final val PrivateOrAccessor = Private | Accessor
final val PrivateOrAccessorOrDeferred = Private | Accessor | Deferred
def forwarder(target: Symbol) = (targs: List[Type]) => (vrefss: List[List[Tree]]) =>
superRef(target).appliedToTypes(targs).appliedToArgss(vrefss)
private def competingMethodsIterator(meth: Symbol): Iterator[Symbol] = {
cls.baseClasses.iterator
.filter(_ ne meth.owner)
.map(meth.overriddenSymbol)
.filter(_.exists)
}
}
|