Possible bugs and/or inconsistencies with capture sets and overriding methods
Closed this issue · 3 comments
Compiler version
3.6.4-RC1
Minimized code
import language.experimental.captureChecking
class C
trait T {
def foo(x: C^{this}): Unit
def bar(c: C^): Unit
def ijk(s: String^): Unit
def xyz(i: Int^): Unit
def test(): T = this
}
object O extends T {
override def foo(x: C): Unit = ???
override def bar(c: C): Unit = ???
override def ijk(s: String): Unit = ???
override def xyz(i: Int): Unit = ???
}Output
sbt:scala3> scala2-library-cc/compile
[info] compiling 1 Scala source to /Users/05st/Projects/scala/scala3/out/bootstrap/scala2-library-cc/scala-3.7.0-RC1-bin-SNAPSHOT-nonbootstrapped/classes ...
[error] -- [E007] Type Mismatch Error: /Users/05st/Projects/scala/scala3/scala2-library-cc/src/scala/concurrent/testing/report.scala:11:20
[error] 11 | def test(): T = this
[error] | ^^^^
[error] | Found: (T.this : T^)
[error] | Required: T
[error] |
[error] | longer explanation available when compiling with `-explain`
[error] -- [E164] Declaration Error: /Users/05st/Projects/scala/scala3/scala2-library-cc/src/scala/concurrent/testing/report.scala:17:17
[error] 17 | override def bar(c: C): Unit = ???
[error] | ^
[error] | error overriding method bar in trait T of type (c: C^): Unit;
[error] | method bar of type (c: C): Unit has incompatible type
[error] |
[error] | longer explanation available when compiling with `-explain`
[error] two errors found
[error] (scala2-library-cc / Compile / compileIncremental) Compilation failed
[error] Total time: 1 s, completed Mar 4, 2025, 8:22:24 p.m.Expectation
This looks like a bug because the override for foo does not have a capture set for C. However, this may be valid because the capture set is empty since this is not a capability. In that case, it seems inconsistent for it to matter in the definition of test, where it throws an error.
Additionally, it seems like String and Int have special behaviour. The overrides for ijk and xyz don't throw an error like it does for bar. The capture sets seem to be ignored in the overrides. Is this intended for primitive types? String is not a primitive type - I would expect it to error like it does with the override for bar.
The point is that inside object O, this is not a capability. So the foo override is legal. The two reported errors are legit, too.
Both Int and String are special-cased in capture checking.
This example was minimized from DefaultBlockContext: https://github.com/scala/scala/blob/3548afcd51d3a60365f8c068d54a8d95c2e45b04/src/library/scala/concurrent/BlockContext.scala#L61