News for hackers. Stuff that matters.
Re:The memory models that underlie programming languages (2016) by drran on Thursday June 10, 2021 @07:15AM (#27459348)
You can use your own allocator in Rust, with your own rules, OR you can use static arrays and then just reset aray length to zero at the end of frame.

Your function is easy to write in (unsafe!) Rust:

https://play.rust-lang.org/?version=stable&mode=debug&editio...

  use lazy_static::lazy_static; // 1.4.0
  use std::mem;

  lazy_static! {
    static ref BUF: [String; 16] = [
      String::with_capacity(1024), String::with_capacity(1024), String::with_capacity(1024), String::with_capacity(1024),
      String::with_capacity(1024), String::with_capacity(1024), String::with_capacity(1024), String::with_capacity(1024),
      String::with_capacity(1024), String::with_capacity(1024), String::with_capacity(1024), String::with_capacity(1024),
      String::with_capacity(1024), String::with_capacity(1024), String::with_capacity(1024), String::with_capacity(1024)
    ];
    static ref BUF_INDEX: usize = 0;
  }

  fn tmpstr() -> &'static mut String { 
   let index_ptr: * const usize = &*BUF_INDEX;
   let index: &'static mut usize = unsafe { mem::transmute(index_ptr) };

   let buf_ptr: * const String = &BUF[*index];
   let ret: &'static mut String = unsafe { mem::transmute(buf_ptr) };

   ret.truncate(0);

   *index = (*index + 1usize) % BUF.len();
   
   return ret;
  }

  fn main(){
    let s1 = tmpstr();
    s1.push_str("Hello, world!");

    let s2 = tmpstr();
    s2.push_str("And hello world again!");

    dbg!(s1, s2);
  }
BTW: It's very good idea for embedded systems.
Re:The memory models that underlie programming languages (2016) by moonchild on Thursday June 10, 2021 @05:49PM (#27466260)
Yes, of course you can express this in rust. The topic at hand is whether it can be expressed in terms of rust's ownership policies. Your example shows that it cannot; it returns an object of static lifetime, avoiding the issue completely.
Re:The memory models that underlie programming languages (2016) by littlestymaar on Friday June 11, 2021 @03:22AM (#27470282)
The topic at hand was about the comparison between C and Rust in terms of memory model. Ownership policies are one restriction safe Rust uses to ensure that the user is adhering to its memory model, but Rust is not limited to safe Rust and you can op-out ownership policies if you use raw pointers.

The difference between Rust and C in terms of memory model isn't ownership, it's “mutable xor shared”.

Re:The memory models that underlie programming languages (2016) by drran on Friday June 11, 2021 @05:39AM (#27471107)
I cannot understand your question about "ownership policies". Rust have only one ownership policy: one owner per object.

It's possible to use pointers to circumvent the restriction and then control when object is destructed using ManuallyDrop[0], so burden of memory bookkeeping will be shifted from Rust compiler to the programmer.

[0]: https://doc.rust-lang.org/core/mem/struct.ManuallyDrop.html

Re:The memory models that underlie programming languages (2016) by scoutt on Friday June 11, 2021 @03:30AM (#27470331)
But String is heap allocated, right?

Can you just declare a static array and return a pointer pointing to any part of it? Like in the C example?

BUF is also visible to other parts of the program, correct? If so, it's not quite similar to the C example.

Re:The memory models that underlie programming languages (2016) by littlestymaar on Friday June 11, 2021 @05:03AM (#27470896)
> Can you just declare a static array and return a pointer pointing to any part of it? Like in the C example?

Indeed:

    lazy_static! {
      static ref BUF: [[u8;1024]; 16] = [
        [0;1024], [0;1024], [0;1024], [0;1024],
        [0;1024], [0;1024], [0;1024], [0;1024],
        [0;1024], [0;1024], [0;1024], [0;1024],
        [0;1024], [0;1024], [0;1024], [0;1024]];
      static ref BUF_INDEX: usize = 0;
    }
(You'll need to re-implement a `push_str` method on arrays yourself though)

> BUF is also visible to other parts of the program, correct? If so, it's not quite similar to the C example.

No, because it's not marked as `pub`, nobody outside the current module can access it.

Re:The memory models that underlie programming languages (2016) by drran on Friday June 11, 2021 @05:25AM (#27471029)
String is heap allocated by default, but String can be made from raw pointer to buffer and buffer length: https://doc.rust-lang.org/std/string/struct.String.html#meth... .

Yes, of course. BTW: You can use a c2rust converter to convert a C code to it exact equivalent in Rust.

No, buf is not exported, so it's "static" in C terminology.

Re:The memory models that underlie programming languages (2016) by scoutt on Friday June 11, 2021 @05:51AM (#27471197)
> No, buf is not exported, so it's "static" in C terminology.

Yes, I know that is not exported. What I wanted to say is that in the C example, no one outside tmpstr(void) can access static char buf[16][1024].

In the Rust example I can access static ref BUF from fn main() function, for example.

Re:The memory models that underlie programming languages (2016) by littlestymaar on Friday June 11, 2021 @07:55AM (#27472087)
> In the Rust example I can access static ref BUF from fn main() function, for example.

Only because in that simple example, BUF was defined directly in the main module.

In a more realistic exemple, BUF and tmpstr would belong to their own module, with only tmpstr being exported (and then accessible). See: https://play.rust-lang.org/?version=stable&mode=debug&editio...