diff options
author | Dmitry Petrashko <dark@d-d.me> | 2016-03-24 20:22:01 +0100 |
---|---|---|
committer | Dmitry Petrashko <dark@d-d.me> | 2016-03-24 20:22:01 +0100 |
commit | 035aff45e89084290b8f67ca49007c3eac00f13f (patch) | |
tree | da73d918daf133ad8ff012a0774eb82fd49bf413 /src | |
parent | 3e43c7f989c48c8e78eb6c7b5ae9bcb301a0c07d (diff) | |
parent | 28a2c76952c753ea2c3efacfad93c87a63227259 (diff) | |
download | dotty-035aff45e89084290b8f67ca49007c3eac00f13f.tar.gz dotty-035aff45e89084290b8f67ca49007c3eac00f13f.tar.bz2 dotty-035aff45e89084290b8f67ca49007c3eac00f13f.zip |
Merge pull request #1104 from dotty-staging/spec-bugs
Improvements & bugs that were discovered while implementing specialization.
Diffstat (limited to 'src')
4 files changed, 23 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled b/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled index 65362f199..7b37c5881 100644 --- a/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled +++ b/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled @@ -30,7 +30,7 @@ import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo */ class DropEmptyCompanions extends MiniPhaseTransform { thisTransform => import ast.tpd._ - override def phaseName = "dropEmpty" + override def phaseName = "dropEmptyCompanions" override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Flatten]) override def transformPackageDef(pdef: PackageDef)(implicit ctx: Context, info: TransformerInfo) = { diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 3445b4c44..8d890902e 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -611,7 +611,7 @@ object Erasure extends TypeTestsCasts{ traverse(newStats, oldStats) } - private final val NoBridgeFlags = Flags.Accessor | Flags.Deferred | Flags.Lazy + private final val NoBridgeFlags = Flags.Accessor | Flags.Deferred | Flags.Lazy | Flags.ParamAccessor /** Create a bridge DefDef which overrides a parent method. * diff --git a/src/dotty/tools/dotc/transform/Memoize.scala b/src/dotty/tools/dotc/transform/Memoize.scala index b775496ae..1e4f8831b 100644 --- a/src/dotty/tools/dotc/transform/Memoize.scala +++ b/src/dotty/tools/dotc/transform/Memoize.scala @@ -68,6 +68,10 @@ import Decorators._ } lazy val field = sym.field.orElse(newField).asTerm + + def adaptToField(tree: Tree) = + if (tree.isEmpty) tree else tree.ensureConforms(field.info.widen) + if (sym.is(Accessor, butNot = NoFieldNeeded)) if (sym.isGetter) { def skipBlocks(t: Tree): Tree = t match { @@ -85,14 +89,15 @@ import Decorators._ case _ => var rhs = tree.rhs.changeOwnerAfter(sym, field, thisTransform) if (isWildcardArg(rhs)) rhs = EmptyTree - val fieldDef = transformFollowing(ValDef(field, rhs)) + + val fieldDef = transformFollowing(ValDef(field, adaptToField(rhs))) val getterDef = cpy.DefDef(tree)(rhs = transformFollowingDeep(ref(field))(ctx.withOwner(sym), info)) Thicket(fieldDef, getterDef) } } else if (sym.isSetter) { if (!sym.is(ParamAccessor)) { val Literal(Constant(())) = tree.rhs } // this is intended as an assertion field.setFlag(Mutable) // necessary for vals mixed in from Scala2 traits - val initializer = Assign(ref(field), ref(tree.vparamss.head.head.symbol)) + val initializer = Assign(ref(field), adaptToField(ref(tree.vparamss.head.head.symbol))) cpy.DefDef(tree)(rhs = transformFollowingDeep(initializer)(ctx.withOwner(sym), info)) } else tree // curiously, some accessors from Scala2 have ' ' suffixes. They count as diff --git a/src/dotty/tools/dotc/transform/MixinOps.scala b/src/dotty/tools/dotc/transform/MixinOps.scala index db89f939b..6cebf7197 100644 --- a/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/src/dotty/tools/dotc/transform/MixinOps.scala @@ -41,11 +41,21 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx: ctx.atPhase(thisTransform) { implicit ctx => cls.info.member(sym.name).hasAltWith(_.symbol == sym) } - + + /** 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 overridenSymbols = meth.allOverriddenSymbols - def needsDisambiguation = !overridenSymbols.forall(_ is Deferred) - def hasNonInterfaceDefinition = overridenSymbols.forall(!_.owner.is(Trait)) + lazy val competingMethods = cls.baseClasses.iterator + .filter(_ ne meth.owner) + .map(meth.overriddenSymbol) + .filter(_.exists) + .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) && isCurrent(meth) && (needsDisambiguation || hasNonInterfaceDefinition || meth.owner.is(Scala2x)) |