scala/scala3

Possible bugs and/or inconsistencies with capture sets and overriding methods

Closed this issue · 3 comments

05st commented

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.