Skip to content

Commit 035aff4

Browse files
committed
Merge pull request #1104 from dotty-staging/spec-bugs
Improvements & bugs that were discovered while implementing specialization.
2 parents 3e43c7f + 28a2c76 commit 035aff4

File tree

5 files changed

+40
-8
lines changed

5 files changed

+40
-8
lines changed

src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo
3030
*/
3131
class DropEmptyCompanions extends MiniPhaseTransform { thisTransform =>
3232
import ast.tpd._
33-
override def phaseName = "dropEmpty"
33+
override def phaseName = "dropEmptyCompanions"
3434
override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Flatten])
3535

3636
override def transformPackageDef(pdef: PackageDef)(implicit ctx: Context, info: TransformerInfo) = {

src/dotty/tools/dotc/transform/Erasure.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ object Erasure extends TypeTestsCasts{
611611
traverse(newStats, oldStats)
612612
}
613613

614-
private final val NoBridgeFlags = Flags.Accessor | Flags.Deferred | Flags.Lazy
614+
private final val NoBridgeFlags = Flags.Accessor | Flags.Deferred | Flags.Lazy | Flags.ParamAccessor
615615

616616
/** Create a bridge DefDef which overrides a parent method.
617617
*

src/dotty/tools/dotc/transform/Memoize.scala

+7-2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ import Decorators._
6868
}
6969

7070
lazy val field = sym.field.orElse(newField).asTerm
71+
72+
def adaptToField(tree: Tree) =
73+
if (tree.isEmpty) tree else tree.ensureConforms(field.info.widen)
74+
7175
if (sym.is(Accessor, butNot = NoFieldNeeded))
7276
if (sym.isGetter) {
7377
def skipBlocks(t: Tree): Tree = t match {
@@ -85,14 +89,15 @@ import Decorators._
8589
case _ =>
8690
var rhs = tree.rhs.changeOwnerAfter(sym, field, thisTransform)
8791
if (isWildcardArg(rhs)) rhs = EmptyTree
88-
val fieldDef = transformFollowing(ValDef(field, rhs))
92+
93+
val fieldDef = transformFollowing(ValDef(field, adaptToField(rhs)))
8994
val getterDef = cpy.DefDef(tree)(rhs = transformFollowingDeep(ref(field))(ctx.withOwner(sym), info))
9095
Thicket(fieldDef, getterDef)
9196
}
9297
} else if (sym.isSetter) {
9398
if (!sym.is(ParamAccessor)) { val Literal(Constant(())) = tree.rhs } // this is intended as an assertion
9499
field.setFlag(Mutable) // necessary for vals mixed in from Scala2 traits
95-
val initializer = Assign(ref(field), ref(tree.vparamss.head.head.symbol))
100+
val initializer = Assign(ref(field), adaptToField(ref(tree.vparamss.head.head.symbol)))
96101
cpy.DefDef(tree)(rhs = transformFollowingDeep(initializer)(ctx.withOwner(sym), info))
97102
}
98103
else tree // curiously, some accessors from Scala2 have ' ' suffixes. They count as

src/dotty/tools/dotc/transform/MixinOps.scala

+14-4
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,21 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx:
4141
ctx.atPhase(thisTransform) { implicit ctx =>
4242
cls.info.member(sym.name).hasAltWith(_.symbol == sym)
4343
}
44-
44+
45+
/** Does `method` need a forwarder to in class `cls`
46+
* Method needs a forwarder in those cases:
47+
* - there's a class defining a method with same signature
48+
* - there are multiple traits defining method with same signature
49+
*/
4550
def needsForwarder(meth: Symbol): Boolean = {
46-
lazy val overridenSymbols = meth.allOverriddenSymbols
47-
def needsDisambiguation = !overridenSymbols.forall(_ is Deferred)
48-
def hasNonInterfaceDefinition = overridenSymbols.forall(!_.owner.is(Trait))
51+
lazy val competingMethods = cls.baseClasses.iterator
52+
.filter(_ ne meth.owner)
53+
.map(meth.overriddenSymbol)
54+
.filter(_.exists)
55+
.toList
56+
57+
def needsDisambiguation = competingMethods.exists(x=> !(x is Deferred)) // multiple implementations are available
58+
def hasNonInterfaceDefinition = competingMethods.exists(!_.owner.is(Trait)) // there is a definition originating from class
4959
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
5060
isCurrent(meth) &&
5161
(needsDisambiguation || hasNonInterfaceDefinition || meth.owner.is(Scala2x))

tests/run/no-useless-forwarders.scala

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
trait A {
2+
def foo(a: Int): Int = a
3+
def bar(a: Int): Int
4+
}
5+
6+
trait B {
7+
def bar(a: Int): Int = a
8+
}
9+
10+
object Test extends A with B{
11+
def main(args: Array[String]) = {
12+
assert(!this.getClass.getDeclaredMethods.exists{x: java.lang.reflect.Method => x.getName == "foo"},
13+
"no forwarder is needed here")
14+
assert(!this.getClass.getDeclaredMethods.exists{x: java.lang.reflect.Method => x.getName == "bar"},
15+
"no forwarder is needed here")
16+
}
17+
}

0 commit comments

Comments
 (0)