Skip to content

Handle case where abstract overrides miss an implementation #14893

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 1 commit into from
Apr 20, 2022
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
9 changes: 9 additions & 0 deletions compiler/src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -361,5 +361,14 @@ object NameOps {
case raw.BANG => UNARY_!
case _ => name
}

/** If this is a super accessor name, its underlying name, which is the name
* of the method that the super accessor forwards to.
*/
def originalOfSuperAccessorName: TermName = name match
case SuperAccessorName(name1) => name1.originalOfSuperAccessorName
case ExpandedName(_, name1) => name1.originalOfSuperAccessorName
case ExpandPrefixName(_, name1) => name1.originalOfSuperAccessorName
case _ => name
}
}
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ object ResolveSuper {
report.error(IllegalSuperAccessor(base, memberName, targetName, acc, accTp, other.symbol, otherTp), base.srcPos)
bcs = bcs.tail
}
assert(sym.exists, i"cannot rebind $acc, ${acc.targetName} $memberName")
sym
sym.orElse {
val originalName = acc.name.asTermName.originalOfSuperAccessorName
report.error(em"Member method ${originalName.debugString} of mixin ${acc.owner} is missing a concrete super implementation in $base.", base.srcPos)
acc
}
}
}
4 changes: 4 additions & 0 deletions tests/neg/i11170.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- Error: tests/neg/i11170.scala:7:15 ----------------------------------------------------------------------------------
7 |abstract class A extends U[String] // error
| ^
| Member method foo of mixin trait U is missing a concrete super implementation in class A.
8 changes: 8 additions & 0 deletions tests/neg/i11170.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
trait T[X] {
def foo(x: X): X
}
trait U[X] extends T[X] {
abstract override def foo(x: X): X = super.foo(x)
}
abstract class A extends U[String] // error

28 changes: 28 additions & 0 deletions tests/neg/i11170a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package apackage {

abstract class A {
protected val x: Int
}
abstract class A2 {
val x: Int
}
}

package bpackage {
import apackage._

trait B extends A {
println(x)
}
trait B2 extends A2 {
println(x)
}
}

package cpackage {
import apackage._
import bpackage._

case class C(override protected val x: Int) extends A with B // error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should compile. "It's just a protected member." The ticket says it compiles if everything is in a single package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But Scala 2.13 also refuses this one. Is that a known bug?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see Scala 3 has a different definition of protected. It disalllows access to protected Java members from traits

illegal access to protected method test in class Base from trait Ext

at scala/bug#3564

Maybe Scala just makes everything public if it wants to do something like that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Scala 3 ticket was noticed at scala/bug#12249 which is just Scala classes. The other link is a Java base class with protected member. I haven't reflected deeply yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about it either. But at least we don't crash anymore, and do the same thing as Scala 2.13 does.

case class C2(override val x: Int) extends A2 with B2
}
21 changes: 21 additions & 0 deletions tests/pos/MathSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
trait MathSig {
def sqrt(x: Double): Double
}

trait MathSpec extends MathSig {
val epsilon = 0.00001
abstract override def sqrt(x: Double) = {
require(x >= 0)
super.sqrt(x)
} ensuring { result =>
(x * x - result).abs < epsilon
}
}

trait MathImpl extends MathSig {
def sqrt(x: Double): Double =
???
}

object Math extends MathImpl
with MathSpec