"out" function arguments?

I think the problem for Rust here is that in those languages, out is generally a parameter mode not a type. So when you have, say, bool TryGet(out string foo) in C#, you can't put an out string into a datatype, and thus the compiler can check that you actually initialize it before the function returns. (With a massive asterisk on that statement, because out doesn't actually exist in the .Net VM, and thus it's actually just a compiler lint and the bytecode is still default-initializing it before passing it as a mut.)

What would it mean to put an &out into a data structure? What happens if you then (safely!) leak that data structure?

2 Likes

In the formulation in my RFC, &out means write-only. As an effect of this, it also does not drop old values, (because that would require at least 1 read). So putting &out in a data structure could mean that the data structure is a proxy that allows you to write into something else.

For example, graphics buffers managed by the OS. It would not be safe to deallocate that buffer, so you would only have a &out reference to the buffer, and therefore you could write to it, but not read from it.

out arguments, as I'm used to them, are what I think your RFC termed &uninit, requiring that

Functions and closures that take a &uninit T argument must initialize it before returning

Which leads to a whole bunch of questions, like "what happens if I make a Vec<&uninit T>?

Rust turning its parameter modes into real types in the pre-1.0 days was a big part of its value, I think, so I'd hate to lose that with a bunch of limitations like "You cannot return an &uninit T". (What would that mean for generics, anyway?)

1 Like

This is expressly forbidden. &uninit is kinda like out in C#, just a compiler hint.

I'm not sure how to turn &uninit into a type. Because of this, I decided that, for now, it is fine if &uninit wasn't a type. If there is a way to change that, then a future RFC could change that if my RFC goes through.

In an older version of my RFC, I did have that you can't return a &uninit T, but that has since been removed.

What I mean by this is that if a function returns normally (without panicking), then all uninitialized values must be initialized. This is useful because it gives some guarantees when calling functions, if you call a function and it takes an &uninit, you know after the function that the value must have been initialized. It allows for purely local analysis of code.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.