<thejpster[m]>
I would point to `&str`, where creating a `&str` from random bytes without checking that they are valid UTF-8 is `unsafe`. But does making an invalid `&str` cause UB, or does it just cause the API to Not Work?
<dngrs[m]>
hmmm, I think there was something written about std::fs and guarantees/checks that Rust cannot make. But where was that...
<dngrs[m]>
"Note that, although read and write methods require a `&mut File`, because of the interfaces for [`Read`] and [`Write`], the holder of a `&File` can still modify the file, either through methods that take `&File` or by retrieving the underlying OS object and modifying the file that way. Additionally, many operating systems allow concurrent modification of files by different processes. Avoid assuming that holding a `&File` means that
<dngrs[m]>
> The Unsafe Rust code just can't trust the Safe Rust code to be written correctly. That said, BTreeMap will still behave completely erratically if you feed in values that don't have a total ordering. It just won't ever cause Undefined Behavior.
<dngrs[m]>
(also what follows the paragraph I quoted)
<dngrs[m]>
s/also/and/
<JamesMunns[m]>
I agree w/ dion that calling unvalidated utf-8 can cause UB if the bytes are not valid
<JamesMunns[m]>
IMO items like voltage regulator are not `unsafe`, because safety is a *language* construct, and the voltage regulator is part of the "system contract" with the language
<JamesMunns[m]>
if you do something that makes your system invalid or to violate the systemic contract (e.g. unmapping the flash you are executing from), the program is invalid, not just unsafe
<dngrs[m]>
#[deny(holding_it_wrong)]
<JamesMunns[m]>
Violating the unsafe preconditions (in this case: from_utf8_unchecked) IS UB, even if it does not immediately cause a crash, or happens towork
<thejpster[m]>
but why is it UB?
<thejpster[m]>
actually, scratch that. I can dig into it myself.
<thejpster[m]>
<dngrs[m]> "the [nomicon](https://doc.rust-..." <- This is excellent. Thanks!
<thejpster[m]>
ok, so to ask a more pointed question ... why is it unsafe to steal an svd2rust handle to a Peripheral? What UB can you cause by racing on MMIO registers? They are all accessed using volatile loads and stores of CPU register size, which is equivalent to what AtomicU32 does.
Kaspar[m] has joined #rust-embedded
<Kaspar[m]>
<thejpster[m]> "ok, so to ask a more pointed..." <- There could be something inside the implementation that assumes unique access, e.g., rmw. So code depends on nothing else modifying e.g., the registers. The type system *can* enforce this, unless bypassed. It might be that bypassing this causes memory safety issues (e.g., concurrent access to DMA peripheral), so it must be prohibited. So bypassing that contract is 'unsafe'.
<JamesMunns[m]>
<thejpster[m]> "ok, so to ask a more pointed..." <- Disagree it is the same as atomic because volatile read/writes don't use ldrex/strex
<JamesMunns[m]>
<thejpster[m]> "ok, so to ask a more pointed..." <- But as for why it is unsafe is mostly "vibes" and because it seemed reasonable at the time
<JamesMunns[m]>
<thejpster[m]> "ok, so to ask a more pointed..." <- (Ah you mean just atomic load/stores, not atomic updates, separate load stores are memory safe but may not be correct)
<Kaspar[m]>
JamesMunns[m]: My understanding was that this is about soundness.
<JamesMunns[m]>
iirc chiptool doesn't make stealing unsafe, but you might get a ptr or something you have to deref? I forget
<JamesMunns[m]>
If you have a moral "&mut" of the peripheral, that can't alias. But if you are clear you only have/need a shared ref to mutate, like atomics, it is morally fine
<JamesMunns[m]>
Yeah, if you accept an arbitrary ptr, definitely unsafe. If a known good pointer for a good location, that's kinda up to you to set the api as safe or not
<thejpster[m]>
> “up to you”
<thejpster[m]>
oh no
<JamesMunns[m]>
By "moral &mut" I specifically mean:
<JamesMunns[m]>
* If you ever make an &mut of struct you are pointing to, or
<JamesMunns[m]>
* you allude to users that they can ASSUME they have exclusive access to the item while they hold an &mut
<JamesMunns[m]>
if you ONLY use ptr methods (not mapped struct references), and ALWAYS tell users that anyone can alias at any time and they might observe tearing/lost writes/etc. and its up to them to CS that, then it's fine
<JamesMunns[m]>
because you are not morally promising exclusivity in your API
<thejpster[m]>
The compromise answer is probably a BSP that uses an atomicbool to let you safely create everything exactly once.
<JamesMunns[m]>
(which I think svd used to do both, may only do the latter now)
<JamesMunns[m]>
I mean that's what svd2rust does?
<JamesMunns[m]>
its a CS bool, but yeah
<JamesMunns[m]>
JamesMunns[m]: re: this: I'm noting the *exclusive* part of &mut is more important here than the *mutable* part.
<thejpster[m]>
This was useful, thanks.
<JamesMunns[m]>
because &mut pointers are both exclusive and mutable, vs & pointers
<thejpster[m]>
A chapter for the embedonomicon perhaps