Skip to content

ResolveSuper: add missing methods overrides for disambiguation #5662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ class Compiler {
new ElimOuterSelect, // Expand outer selections
new AugmentScala2Traits, // Expand traits defined in Scala 2.x to simulate old-style rewritings
new ResolveSuper, // Implement super accessors and add forwarders to trait methods
new PrimitiveForwarders, // Add forwarders to trait methods that have a mismatch between generic and primitives
new FunctionXXLForwarders, // Add forwarders for FunctionXXL apply method
new ArrayConstructors) :: // Intercept creation of (non-generic) arrays and intrinsify.
List(new Erasure) :: // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements.
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1125,10 +1125,10 @@ object SymDenotations {
final def memberCanMatchInheritedSymbols(implicit ctx: Context): Boolean =
!isConstructor && !is(Private)

/** The symbol, in class `inClass`, that is overridden by this denotation. */
final def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol =
/** The symbol, in class `inClass`, that is overridden by this denotation in class `siteClass`.*/
final def overriddenSymbol(inClass: ClassSymbol, siteClass: ClassSymbol = owner.asClass)(implicit ctx: Context): Symbol =
if (!canMatchInheritedSymbols && (owner ne inClass)) NoSymbol
else matchingDecl(inClass, owner.thisType)
else matchingDecl(inClass, siteClass.thisType)

/** All symbols overridden by this denotation. */
final def allOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] =
Expand All @@ -1142,7 +1142,7 @@ object SymDenotations {

private def overriddenFromType(tp: Type)(implicit ctx: Context): Iterator[Symbol] =
tp.baseClasses match {
case _ :: inherited => inherited.iterator map overriddenSymbol filter (_.exists)
case _ :: inherited => inherited.iterator.map(overriddenSymbol(_)).filter(_.exists)
case Nil => Iterator.empty
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2103,7 +2103,7 @@ object messages {
case _ /* Signature.FullMatch */ => "\nThe definitions have matching type signatures after erasure."
}
} else ""
hl"${decl.showLocated} is already defined as ${previousDecl.showDcl} at line ${previousDecl.pos.line + 1}." + details
hl"${decl.showLocated} is already defined as ${previousDecl.showDcl} ${if (previousDecl.pos.exists) s"at line ${previousDecl.pos.line + 1}" else ""}." + details
}
val explanation: String = ""
}
Expand Down
24 changes: 1 addition & 23 deletions compiler/src/dotty/tools/dotc/transform/MixinOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,6 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont
meth.annotations.nonEmpty && JUnit4Annotations.exists(annot => meth.hasAnnotation(annot))
}

/** 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: FlagSet = Private | Accessor
final val PrivateOrAccessorOrDeferred: FlagSet = Private | Accessor | Deferred

Expand All @@ -104,7 +82,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont
private def competingMethodsIterator(meth: Symbol): Iterator[Symbol] = {
cls.baseClasses.iterator
.filter(_ ne meth.owner)
.map(meth.overriddenSymbol)
.map(base => meth.overriddenSymbol(base, cls))
.filter(_.exists)
}
}
41 changes: 0 additions & 41 deletions compiler/src/dotty/tools/dotc/transform/PrimitiveForwarders.scala

This file was deleted.

1 change: 0 additions & 1 deletion docs/docs/internals/overall-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ phases. The current list of phases is specified in class [Compiler] as follows:
new ElimOuterSelect, // Expand outer selections
new AugmentScala2Traits, // Expand traits defined in Scala 2.x to simulate old-style rewritings
new ResolveSuper, // Implement super accessors and add forwarders to trait methods
new PrimitiveForwarders, // Add forwarders to trait methods that have a mismatch between generic and primitives
new FunctionXXLForwarders, // Add forwarders for FunctionXXL apply method
new ArrayConstructors) :: // Intercept creation of (non-generic) arrays and intrinsify.
List(new Erasure) :: // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements.
Expand Down
19 changes: 19 additions & 0 deletions tests/run/mixin-overrides.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
trait Foo[A] {
def op(x: A): Int
}
trait Bar[A] extends Foo[A] {
override def op(x: A): Int = 1
}
trait Baz[A] extends Foo[A] {
override def op(x: A): Int = 2
}
trait Qux[A] extends Bar[A] with Baz[A]

class QInt extends Qux[Int]

object Test {
def main(args: Array[String]): Unit = {
val qint = new QInt
assert(qint.op(1) == 2) // Used to fail with java.lang.IncompatibleClassChangeError: Conflicting default methods: Bar.op Baz.op
}
}