Description
Compiler version
3.3.1
Minimized code
type DiagnosticConsturctor = (Int) => DiagnosticSet
final class Diagnostic
final class DiagnosticSet(elements: List[Diagnostic] = List())
enum Result:
case Success extends Result
case Failure(diagnose: DiagnosticConsturctor) extends Result
def diagnose(n: Int): DiagnosticSet =
this match
case Success => DiagnosticSet()
case Failure(d) => d(n)
@main def drive(): Unit =
val r : Result = Result.Failure((n) => DiagnosticSet(List(Diagnostic())))
r.diagnose(1)
Output
Stack overflow
Expectation
The program should run to completion.
My understanding of the issue is that the compiler resolves d
to the method defined as member of Result
rather than the case value of Failure
. The stack trace is very confusing, though, as it reports a ping pong between the call in the match expression and the definition of the Failure
case.
Note that a compile-time error is produced if the domain of diagnose
is empty:
type DiagnosticConsturctor = () => DiagnosticSet
enum Result:
case Success extends Result
case Failure(diagnose: DiagnosticConsturctor) extends Result
def diagnose(): DiagnosticSet = ???
In this case, the compiler complains that:
overriding method diagnose in class Result of type (): DiagnosticSet; value diagnose of type DiagnosticConsturctor needs
override
modifier
The reported issue can be fixed by renaming either the case value or the method.
Although this reproducer shows bad class design in Scala (buggy behavior aside), it is representative of a very reasonable setup for developers coming from Swift. Hence it might serve as a reference in the future to remember how Swift users can get intro trouble.