0

When implementing core::fmt::Write for an avr serial monitor, calling unwrap on write_str writes what looks like a compiler error to the output. Calling write_fmt in any capacity crashes, but I think these problems might be related. I'm using a custom target for avr: which is

{
    "arch": "avr",
    "cpu": "atmega328p",
    "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
    "max-atomic-width": 0,
    "env": "",
    "executables": true,
    "linker": "avr-gcc",
    "linker-flavor": "gcc",
    "linker-is-gnu": true,
    "llvm-target": "avr-unknown-unknown",
    "os": "unknown",
    "position-independent-executables": false,
    "exe-suffix": ".elf",
    "eh-frame-header": false,
    "pre-link-args": {
      "gcc": ["-mmcu=atmega328p"]
    },
    "late-link-args": {
      "gcc": ["-lgcc", "-lc"]
    },
    "target-c-int-width": "16",
    "target-endian": "little",
    "target-pointer-width": "16",
    "vendor": "unknown"
}

When calling serial.write_str("hello world"); it prints "hello world" like normal, but if I call serial.write_str("hello world").unwrap(); it instead prints part of a longer string. The longer the message, the more of this string prints, and I think the final string is:

args.len()C:\Users\Jett\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\fmt\mod.rsunsafe precondition(s) violated: slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed 'isize::MAX'called 'Option::unwrap()' on a 'None' valueC:\Users\Jett\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\char\convert.rsC:\Users\Jett\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\str\iter.rsC:\Users\Jett\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\str\validations.rsErrorattempt to add with overflowC:\Users\Jett\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\iter\traits\accum.rsunsafe precondition(s) violated: slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed 'isize::MAX'attempt to add with overflowunsafe precondition(s) violated: slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed 'isize::MAX'C:\Users\Jett\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rust

Update

Here's the implementation:

impl Write for Serial {
    fn write_str(&mut self, s: &str) -> core::fmt::Result {
        for c in s.chars() {
            self.transmit(c as u8);
        }
        Ok(())
    }
}
Colonel Thirty Two
  • 23,953
  • 8
  • 45
  • 85
Kestrel
  • 3
  • 2
  • Adding this unwrap also increases the size of the executable from ~3KB to ~8KB – Kestrel Jan 30 '23 at 17:27
  • I guess this is the only panic in your code, and so the compiler pulls the whole panic machinery if it is there. But I have no idea why it prints that string. – Chayim Friedman Jan 30 '23 at 17:49
  • 2
    What specifically is the question you want an answer to? Do you want confirmation about whether this is really a compiler bug? Do you want a workaround? Or something else? – kaya3 Jan 30 '23 at 18:01
  • Hopefully a workaround, I'm just trying to get a simple `println!()` working. – Kestrel Jan 30 '23 at 18:08

1 Answers1

0

After a bit more testing, it turns out that adding lto = true to [profile.dev] in Cargo.toml fixes this bug.

Kestrel
  • 3
  • 2