Earlier quoted context omitted.
A Rust program can trivially return a tuple of values, so it doesn't need out params.
Out params are needed to ensure zero-copy in-place initialization of large objects, i.e. what C++ does with placement new. You can sort of fake it with MaybeUninit https://doc.rust-lang.org/std/mem/union.MaybeUninit.html but it's quite fiddly, requires unsafe code, and has undesirable effects on the layout of containing objects.
Should small Rust structs be passed by-copy or by-borrow? (2019)
201–210 of 238 posts
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#202Earlier quoted context omitted.
I would still consider myself a go novice, but I have been burned a number of times passing simple objects by reference and then that object gets mutated causing subtle bugs. Also, go is happy to blow your foot off if you take the reference of a loop variable. Although, there is a proposal to fix that. Generally I find that less bugs get introduced when using copy instead of pass by reference, but I’m sure others hav…
This is about rust though and thats not really possible there (at least to my knowledge). You should get a compiler error if you attempt this. I got very little experience in rust though, so there might be a way (I'm just not aware of) to circumvent this check
https://doc.rust-lang.org/reference/interior-mutability.html
Usually (read: near universally) something that provides interior mutability will implement a runtime check to protect you (eg, a lock), but you could make a footgun if you were cavalier about it. And recent I misused a framework (I kept a value returned by the framework around that should've been dropped) without realizing it was holding locks internal to the framework, and ended up with a tricky to diagnose deadlock (though only tricky before I hadn't read the documentation as closely as I should've).
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#203Earlier quoted context omitted.
Yeah inline is an absolute classic for this. The number of uncommented __attribute__((always_inline))s I see in C code drives me crazy. There are absolutely legitimate reasons to use that attribute but there should ALWAYS be a comment about why, so that later readers know in what conditions they can safely remove it.
In the old days I saw C code with massive overuse of the "register" keyword. Meaning this variable should be kept in a register. Someone had ove 12 of these in one function back when that was waaaay more variables then processors had registers. Good thing modern register allocation by compilers makes this irrelevant.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#204Earlier quoted context omitted.
Ugh, you are right but then someone comes and uses this to rationalize not including things like map, filter and reduce in a language because they are supposedly too complicated and you can just do it with a for loop
I work in a Rust codebase that uses a lot of functional functions, and I’ll say this: on average the imperative style takes less lines of code and less indentation. I also find it more readable personally, and idiomatic.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#205I don’t feel like this gave a satisfactory answer the question. Since everything was inlined, the argument passing convention made no difference in the micro benchmarks. But what happens when it does not inline? Then you would actually be testing by-borrow be by-copy instead of how good rust is at optimizing.
In Rust it's considered idiomatic to pass things by-value whenever you can. Usually this is also the most performant option, since it avoids dereferencing in the callee. Of course, if your struct is truly enormous, you may want to break this rule to avoid large copies. But in that case you probably want to Box the struct anyway. Of course, if your struct contains something that can't be copied--like a Vec --you'll ha…
(The other direction is trickier, since by-ref implies the desire to observe aliasing, even though that's usually not expected in practice - but the compiler cannot tell.)
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#206Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#207Earlier quoted context omitted.
> This is one advantage of Ada, where parameters are abstractly declared as "in" or "in out" or "out". Also Fortran has "in", "inout" and "out".
C++23 is not too late to the party https://en.cppreference.com/w/cpp/memory/out_ptr_t/out_ptr
Better yet when you prohibit such arguments from aliasing (or at least make no-alias the default) - now the compiler can also implement "in out" by copying the value back and forth, if it's faster than indirection.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#208Earlier quoted context omitted.
As long as the calling convention is deterministic from the declaration of the function it should be fine right?
If it's deterministic, the compiler cannot actually choose the best way to optimise it.
But also, the ABI only matters between two pieces that are separately compiled. A static binary optimized at link-time doesn't have to care.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#209Earlier quoted context omitted.
Agreed - and this applies in nearly every language: start simple, trust your compiler, and optimize only when performance becomes untenable.
This advice hinges hugely on what "start simple" really means. There's a ton of counter-examples here where that just isn't true at all depending on what you're calling "simple". In particular JIT'd languages can be especially problematic here. An example would be using Java's Streams interfaces to do something that could be done without much difficulty with a regular boring ol' for loop. At the end of the day you're…
Not really. I'm just hoping that it will be "fast enough", which in the vast majority of cases it is.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#210This is one advantage of Ada, where parameters are abstractly declared as "in" or "in out" or "out". The compiler can then decide how to best implement it for that specific size and architecture.