(&v != &v) for function parameter

You describe the argument passing in C which is by value. Zig, on the other hand, has PRO (Parameter Reference Optimization) where Zig compiler chooses behind your back whether to pass by value or by constant reference. Small objects are passed by value, large objects by const pointer. There is a great video with the title something like “Attack of the Killer Features” that goes in much more details. Highly recommended.

1 Like

In PRO the argument is either value or a constant reference. The constant reference is a constant pointer that is implicitly desugared as p.* everywhere so that for the user the pointer dereference is transparent. In such a case taking address of the argument returns the value of the pointer which is the address of the object, not the address of the pointer. It is similar to how C++ references work.

Replying to @dude_the_builder and @slonik-az.

The ideia is for PRO to be completely transparent to the user. Zig’s goal is for us to pass by value as a default. You should never need to think about how the compiler decided to actually pass the parameter behind the scenes, always assume that it passed by value. In fact, we shouldn’t even need to know that the compiler is doing this optimization. The only thing you would need to know is that passing by value won’t cause performance problems. In fact, it should have better performance.
Clearly, this isn’t working, but it’s a flaw in the implementation, not in the idea itself. In the other post in this forum, I argued that I thought the implementation problems were unsolvable, but you might have seen Andrew’s reply. He has not given up.
When (or if, with Andrew’s pardon :man_shrugging:) Zig achieves its goal, than parameter passing in Zig will be much simpler than C. Just pass by value, period. Only pass pointers if you actually really need the address.

1 Like

It would actually be fine if the language did not require a stable pointer address for references to parameters. If you need this property to hold, you’re doing something wrong.

Bad take. There’s no logical reason that converting a value into a reference twice should produce aliases. The real problem is your code should not depend on this property.

When I read this thread, I see an implication that I’m not prioritizing important issues enough. In reality, the issue is not actually important. What’s important is coming up with a coherent design with respect to aliasing, and whether function parameters get a stable pointer when referenced twice doesn’t actually matter at all compared to the other design considerations that will decide whether or not the language gains this property.

5 Likes

In case you have not seen it, here it the great video ATTACK of the KILLER FEATURES by Martin Wickham (aka SpexGuy). One cannot explain it better. Should be a required prerequisite for any discussion about PRO, RLS and their interactions.

Yes, I’ve seen it. it’s an excelent talk. But we have to differentiate between the goal and the current state of things.
Zig’s goal: Always pass by value and don’t worry whats happening behind the scenes. Passing by reference doesn’t exist. We promise you’ll get great performance.
Current state of things: PRO has implementation flaws that force us to know what’s happening behind the scenes. We have to think about what happens if the compiler decides to pass by reference.

5 Likes

@LucasSantos91: I wish you were right and in the end of the day both PRO and RLS will be implementation details that a user can be ignorant of. Curious to see what set of tricks Andrew has up his sleeve.

1 Like

If he pulls that off, the Zig team should really publish an article about it. It’s going to be a great addition not only to Zig, but to computer science as whole. It’s quite a tricky problem, as the talk you linked has shown. It’s awesome that Andrew is still confident they’ll solve it. I was under the impression everyone had just given up.

Chandler Carruth claims he solved (or rather avoided) it in Carbon.

Doesn’t exist as in “it’s there, but you should use it only if you REALLY need it and you know what you’re doing”, or as in “you can’t do it”?

We’re talking about the target, not the current state of affairs, just to be clear.

No, I’m describing aliasing within the meaning of the topic title.
If you have something like fn func(s1: *Struct, s2: *Struct) and then
call it like func(&s, &s), then, of course, both s1 and s2 inside
the function are aliases for the s, but not for each other, they are
at different locations, &s1 != &s2.

I am by no means languages/compilers designer and so I’m not a person to give advice, but wait…

Having a function signature like fn func(a: SmallThing), I know that type of &a is *SmallThing. But if I have some fn func(a: LargeThing) and compiler (behind my back:frowning: ) decided to pass a pointer, what is the type of &a then? Is it *LargeThing? Or is it **LargeThing?

Imho, it is a complete mess and it is even worse than C#'s or D’s “value types” and “reference types”, because I know (I mean C#/D) that struct instances (value type) are always passed as a copy and class instances (reference type) are always passed by reference (syntactically there is no difference, but I know where I have structs and where I have classes)… But if this is done implicitly, “behind my back”… oh, NO, I would better write in C.

I did not watch it yet, but found an interesting duscussion.

Nobody cares that &s1 != &s2. It is bad enough that s1 == s2 but you can at least check for it in your code.

It is *LargeThing but it may refer to its address on the calling site (when implicitly passed by reference) or address of the temporary (if implicitly passed by value). And you do not know it because it is happening behind your back. The only way to be certain is explicitly pass by pointer in the function signature or by forcing C calling convention (did not try). Carbon lang resolves it by simply banning address operator for function parameters. Out of sight – problem gone. :slight_smile:

Really? @Durobot and me was wondering why take an address of a function argument at all? And you replied - for “aliasing detection”. But functions arguments can not be aliases for each other, they are at different locations just by definition, regardless of whether they are pointers or not. Yes-yes-yes, they may refer to the same location, and so they can be aliases for that location, but we are talking about addresses of arguments themselves - and they are always different.

1 Like

At first I thought it’s really cool feature, but it’s not, because actually there is at least one simple reason why one may want to do this - just to print them out to look at stack frame layout with learning/debugging purpose.

Well, this is the thing. If the parameter was passed in register, than looking at the stack won’t show you the parameter. It’ll show you an object that was placed there just for your viewing pleasure.

4 Likes

I’m not sure this outweighs possible optimizations the lack of this feature may bring. But then again, I’m very new to this PRO business.

1 Like

Sheez, this is like quantum physics man! lol

2 Likes

Yep. The Observer effect.

2 Likes

I think we are talking past each other and I apologize if I am not being clear enough. Let’s do it once again but this time very explicitly. Let o1 and o2 be distinct objects. p1 and p2 are two pointers that can point either to two distinct objects p1=&o1; p2=&o2; or to the same object p1=&o1; p2=&o1;. In the latter case p1==p2 and it is aliasing. It does not matter that p1 and p2 themselves are in different locations &p1 != &p2. Or more precisely if &p1==&p2 in C-lingo it would mean that pointer-to-pointer are aliases.

Now, what it all has to do with Zig PRO? If i have a call foo(o1,o1) there are 4 logical possibilities that PRO can take behind your back: (1) pass both arguments by value meaning (&arg1 != &arg2); (2) path both by constant reference (&arg1 == &arg2); (3) and (4) when one arg is passed by value while another by reference, also (&arg1 != &arg2).

Uh, done. I cannot add anything more beyond what I already said and do not want to repeat myself. This is my last reply in this sub-thread.

1 Like