Skip to content

Logger trait's write_view/write_substring mutual defaults allow infinite recursion at runtime #3805

Description

@auxsoft

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions