Background
The Logger trait in builtin/traits.mbt defines write_view and write_substring with mutually recursive default implementations.
This pattern appears to be intended to allow implementers to provide either method, with the other derived automatically—similar to how Show relies on output and to_string.
And
Unlike Show, which uses #must_implement_one(output, to_string) to enforce that at least one of its mutually defaulted methods is implemented, Logger has no equivalent enforcement for write_view and write_substring.
But
A type can implement Logger while overriding neither write_view nor write_substring. Such code compiles successfully. A deprecation warning is produced for impl write_substring.
Calling write_string, write_view, or write_substring on an instance of that type then triggers infinite mutual recursion between the two default implementations, causing a stack overflow at runtime.
Minimal reproduction:
struct MyLogger {
mut buf : String
}
impl Logger for MyLogger with write_char(self, c) {
self.buf = self.buf + c.to_string()
}
fn main {
let l = MyLogger::{ buf: "" }
l.write_string("hello")
println("Result: " + l.buf)
}
Running this with moon run compiles successfully but crashes with a stack overflow.
Background
The
Loggertrait inbuiltin/traits.mbtdefineswrite_viewandwrite_substringwith mutually recursive default implementations.This pattern appears to be intended to allow implementers to provide either method, with the other derived automatically—similar to how
Showrelies onoutputandto_string.And
Unlike
Show, which uses#must_implement_one(output, to_string)to enforce that at least one of its mutually defaulted methods is implemented,Loggerhas no equivalent enforcement forwrite_viewandwrite_substring.But
A type can implement
Loggerwhile overriding neitherwrite_viewnorwrite_substring. Such code compiles successfully. A deprecation warning is produced forimpl write_substring.Calling
write_string,write_view, orwrite_substringon an instance of that type then triggers infinite mutual recursion between the two default implementations, causing a stack overflow at runtime.Minimal reproduction:
Running this with
moon runcompiles successfully but crashes with a stack overflow.