# Result Location Semantics

**URL:** <https://ziggit.dev/t/result-location-semantics/3579>\
**Category:** Explain\
**Tags:** language\
**Created:** [March 16, 2024, 2:24pm UTC](https://ziggit.dev/t/result-location-semantics/3579 "2024-03-16T14:24:35Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![dimdin](https://ziggit.dev/user_avatar/ziggit.dev/dimdin/32/1457_2.png) [@dimdin](https://ziggit.dev/u/dimdin)\
**Post date:** [March 16, 2024, 2:24pm UTC](https://ziggit.dev/t/result-location-semantics/3579/1 "2024-03-16T14:24:35Z")

</div>

Result Location semantics added to the [Language Reference](https://ziglang.org/documentation/master/#Result-Location-Semantics), authored by @mlugg  
This explains “the primary mechanism of type inference in the language”.

---

<div class="post-metadata">

**Author:** ![mlugg](https://ziggit.dev/user_avatar/ziggit.dev/mlugg/32/437_2.png) [@mlugg](https://ziggit.dev/u/mlugg)\
**Post date:** [March 16, 2024, 3:25pm UTC](https://ziggit.dev/t/result-location-semantics/3579/2 "2024-03-16T15:25:40Z")

</div>

Note that RLS has never been called or referred to as “r-value semantics”, and if you’re referring to the concept of lvalue and rvalue as in C, those concepts don’t quite map neatly to Zig (or at least, their definitions become more subtle), and aren’t really related to RLS in any case. I think the term “r-value” in this post could be a bit confusing!

---

<div class="post-metadata">

**Author:** ![dimdin](https://ziggit.dev/user_avatar/ziggit.dev/dimdin/32/1457_2.png) [@dimdin](https://ziggit.dev/u/dimdin)\
**Post date:** [March 16, 2024, 3:36pm UTC](https://ziggit.dev/t/result-location-semantics/3579/3 "2024-03-16T15:36:58Z")

</div>

Yes, I was referring to the Lvalue (but wrote rvalue) concept of CPL (ancestor of BCPL,B,C).  
I removed it from the post. Yes, it was confusing, and the rvalue was wrong.

---

<div class="post-metadata">

**Author:** ![Calder-Ty](https://ziggit.dev/user_avatar/ziggit.dev/calder-ty/32/10237_2.png) [@Calder-Ty](https://ziggit.dev/u/Calder-Ty)\
**Post date:** [March 17, 2024, 12:13pm UTC](https://ziggit.dev/t/result-location-semantics/3579/4 "2024-03-17T12:13:12Z")

</div>

I’ve read through the linked section. The part about location semantics makes sense, but the table I find confusing/mystifying. 1. What does it mean that “x has no result location”? Is that just a meaning that the expression doesn’t “move” x? 2. What does it mean that the Parent Expression is Ptr? I get that a lot of those deal with pointers (or arrays, etc.) but not all of the do, or at least not obviously to me.

I ask not to be critical, but to understand better. I read any RLS occasionally here on the threads, but want to understand what’s the big deal.

---

<div class="post-metadata">

**Author:** ![dimdin](https://ziggit.dev/user_avatar/ziggit.dev/dimdin/32/1457_2.png) [@dimdin](https://ziggit.dev/u/dimdin)\
**Post date:** [March 17, 2024, 12:46pm UTC](https://ziggit.dev/t/result-location-semantics/3579/5 "2024-03-17T12:46:07Z")

</div>

> [@Calder-Ty](#):
>
> 1. What does it mean that “x has no result location”?

The compiler must allocate a location to store the result (cannot optimize it using an existing location).

> [@Calder-Ty](#):
>
> 1. What does it mean that the Parent Expression is Ptr?

Cannot find it anywhere. `Parent Result Type` is used in the first table and you can replace it with `Result Type`; there is no special meaning for `parent`.

---

<div class="post-metadata">

**Author:** ![dimdin](https://ziggit.dev/user_avatar/ziggit.dev/dimdin/32/1457_2.png) [@dimdin](https://ziggit.dev/u/dimdin)\
**Post date:** [March 17, 2024, 12:51pm UTC](https://ziggit.dev/t/result-location-semantics/3579/6 "2024-03-17T12:51:03Z")

</div>

> [@Calder-Ty](#):
>
> I read any RLS occasionally here on the threads, but want to understand what’s the big deal.

This video explains them all:

- parameter reference optimization
- result location semantics

and their current problems.

[![](https://ziggit.dev/uploads/default/original/1X/70fc7c4eb04d7d02787a4b40cf271f86ab8eb734.jpeg "ATTACK of the KILLER FEATURES - Martin Wickham - Software You Can Love Vancouver 2023") ](https://www.youtube.com/watch?v=dEIsJPpCZYg)

---

<div class="post-metadata">

**Author:** ![Calder-Ty](https://ziggit.dev/user_avatar/ziggit.dev/calder-ty/32/10237_2.png) [@Calder-Ty](https://ziggit.dev/u/Calder-Ty)\
**Post date:** [March 17, 2024, 2:50pm UTC](https://ziggit.dev/t/result-location-semantics/3579/7 "2024-03-17T14:50:20Z")

</div>

Sorry I meant Result Location in the second table.

---

<div class="post-metadata">

**Author:** ![dimdin](https://ziggit.dev/user_avatar/ziggit.dev/dimdin/32/1457_2.png) [@dimdin](https://ziggit.dev/u/dimdin)\
**Post date:** [March 17, 2024, 4:20pm UTC](https://ziggit.dev/t/result-location-semantics/3579/8 "2024-03-17T16:20:53Z")

</div>

In the second table, column Result Location, there two values: `-` and `ptr`.

- “`-`” means nothing (e.g. in `var val: T = x` =\> result location of `x` is `&val`)
- “`ptr`” is just a name for the 1st column expression (e.g. in `ptr` = `.{ .a = x }` =\> result location of `x` is `&ptr.a`)

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 18, 2024, 1:02am UTC](https://ziggit.dev/t/result-location-semantics/3579/9 "2024-03-18T01:02:18Z")

</div>

I read it and I have to admit, that example went past my bat until I looked at it more than once. It’s hard to express the idea being presented, though. I don’t have a better way of saying what it’s trying to communicate.

---

<div class="post-metadata">

**Author:** ![chaoyangnz](https://ziggit.dev/user_avatar/ziggit.dev/chaoyangnz/32/2399_2.png) [@chaoyangnz](https://ziggit.dev/u/chaoyangnz)\
**Post date:** [May 22, 2024, 11:01am UTC](https://ziggit.dev/t/result-location-semantics/3579/10 "2024-05-22T11:01:29Z")

</div>

I am curious about how we take advantage of the info to infer the result type without explicitly passing the type as a an argument.

Built-in functions can know result type, so the result type can be omitted as the first argument, like @intCast()

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [May 22, 2024, 4:26pm UTC](https://ziggit.dev/t/result-location-semantics/3579/11 "2024-05-22T16:26:43Z")

</div>

> [@chaoyangnz](#):
>
> I am curious about how we take advantage of the info to infer the result type without explicitly passing the type as a an argument.

This has potential to make certain comptime functions smoother. Something like this, which doesn’t currently work:

```zig
fn cast(a: anytype) T {
    return @as(T, a);
}

test "cast mechanism" {
    const result: u64 = cast(@as(u8, 5));
    std.testing.expectEqual(5, result);
}

```

It couldn’t be `T` because it’s just a convention to use T for generic types, there could be a real `T` struct definition or whatever. So it would need to be a keyword, for the sake of argument:

```zig
fn cast(a: anytype) anyresult {
    return @as(anyresult, a);
}

```

This is a possible construct because of result-location semantics. I don’t know if `anyresult` is the clearest possible keyword here, but it tracks with other constructs in the language.

There’s a common pattern in comptime fn specifications where a type is passed in, usually as the first arguement. For the common case where that type is specifying the result type of the function, something like this could be used instead, leading to cleaner code.

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [May 22, 2024, 4:53pm UTC](https://ziggit.dev/t/result-location-semantics/3579/12 "2024-05-22T16:53:37Z")

</div>

Small side tangent… I remember seeing a discussion about deduced return types. I can’t remember if it was a git issue or if someone mentioned it on here, but that idea has been kicked around. I believe (could be wrong) that they are still considering it.

I think that’d be a great addition if it can be done smoothly. In a meta programming context, we often have to write something like:

```zig
pub fn foo(...) blk: { // code here to deduce type
pub fn foo(...) FooReturn(...) // helper function
pub fn foo(...) switch(...)
pub fn foo(...) if (...) T else U

```

Actually, I believe it was something @marler8997 commented on.

---

<div class="post-metadata">

**Author:** ![nyc](https://ziggit.dev/user_avatar/ziggit.dev/nyc/32/1167_2.png) [@nyc](https://ziggit.dev/u/nyc)\
**Post date:** [May 26, 2024, 12:54pm UTC](https://ziggit.dev/t/result-location-semantics/3579/13 "2024-05-26T12:54:21Z")

</div>

Anybody know if there are any plans to make it any smarter and see though some compuations, or is that no possible. Even the simplest computations force wildly lengthy cast or yet another line with another made up varibles not to do the cast first:

```zig
pub noinline fn f(x: i32, y: u32) i32 {
    const z: i32 = x + @as(i32, @intCast(y)); // all this for x + y
    return z;
}

```

IIf RLS was supposed to make code clearer and casting easier, it is failing horribly. With RLS came the decision to remove all the target cast types from the cast functions `@intCast(i32, y)` would be soooo much nicer. RLS seems like it was half way added, not taken avantage of, and left in a worst of both worlds state.

I feel likes its a negative at this point even though I liked the idea of it originally. I feel like half my code is casting sometimes (not too far off the mark for some functions).

For a system langauge, it can be really hard to do system-y stuff sometimes. I don’t think it uniquely gives any optimizations that can’t be done in other ways (eg, RVO), and it definitely makes the code less readable.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [May 26, 2024, 6:29pm UTC](https://ziggit.dev/t/result-location-semantics/3579/14 "2024-05-26T18:29:33Z")

</div>

RLS could be more sophisticated for sure. I hit this recently:

```zig
    var buf: [256]u8 = undefined;
    var buf_alloc = FixedBufferAllocator.init(&buf);
    const alloc = buf_alloc.allocator();

```

The only reason `buf_alloc` exists is because of the `const` default, so I have to cast it to `var` instead of just this:

```zig
    var buf: [256]u8 = undefined;
    const alloc = FixedBufferAllocator.init(&buf).allocator();

```

Analysis of the whole expression would reveal that the chaining is perfectly legal. The compiler just needs to be a bit lazier about assigning constness to intermediate expressions.

This, however:

> [@nyc](#):
>
> ```zig
> pub noinline fn f(x: i32, y: u32) i32 {
> const z: i32 = x + @as(i32, @intCast(y)); // all this for x + y
> return z;
> }
> 
> ```

Is a downcast. Half of the legal values of a `u32` aren’t representable in `i32`. C’s loose rules around promotion can lead to absolutely teeth-grinding bugs, which are difficult to surface and correct.

That said, downcasting does happen a lot. A builtin `@downCast(i32, y)` would be a good compromise here.

---

<div class="post-metadata">

**Author:** ![nyc](https://ziggit.dev/user_avatar/ziggit.dev/nyc/32/1167_2.png) [@nyc](https://ziggit.dev/u/nyc)\
**Post date:** [May 26, 2024, 6:46pm UTC](https://ziggit.dev/t/result-location-semantics/3579/15 "2024-05-26T18:46:05Z")

</div>

Having to do a cast on lossy trype changes is totally fine. It is the the sheer amont of syntax involved in doing it. Gd help you if you have to cast 2 variables. `@intCast(T, elem)` would be fine, and that’s the way it used to work. But when RLS came along all those type arguements got remvoved now and RLS isn’t sophisticated enough to see thought the computation ie, `const z: i32 = x + @intCast(y)` doesn’t work (where x is i32 and y is u32).

I don’t know if there are technical reasons for RLS not being able to see though even the most trivial computation and letting @intCast work like you would expect it to, but now it seems like almost all my casts require the @xFromY and the @as(T, …) both. removing the type arguments was premature until RLS could be made to be smarter.

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [May 26, 2024, 7:03pm UTC](https://ziggit.dev/t/result-location-semantics/3579/16 "2024-05-26T19:03:34Z")

</div>

Zig functions aren’t variadic, so a one-argument `@intCast` makes more sense when there’s a result location in play. RLS _could_ figure that out for you, but I reckon it probably shouldn’t, it’s too close to C casting rules. Explicit is good when evoking potentially-undefined behavior.

Re-adding the two argument `@intCast` as `@downCast(T, v)` would reduce the noise to a tolerable level, while keeping things explicit.

---

<div class="post-metadata">

**Author:** ![nyc](https://ziggit.dev/user_avatar/ziggit.dev/nyc/32/1167_2.png) [@nyc](https://ziggit.dev/u/nyc)\
**Post date:** [May 26, 2024, 7:13pm UTC](https://ziggit.dev/t/result-location-semantics/3579/17 "2024-05-26T19:13:07Z")

</div>

> [@mnemnion](#):
>
> Zig functions aren’t variadic

lol. nope. @TypeOf’s function definition is @TypeOf(…) because you can give it any number of argument. There’s a few others too I think.

Im not saying RLS should do the cost automatically, Im saying the @intCast that uses RLS to determine the target type can;t figoure out the target type so you have this mess of @as(T, @someotherCast(,…)) all over the place, RLS needs to see through that compuation to get @intCast to do its job.

I still think @intCast should be required for lossy casts, but RLS needs to do a better job and figure out the target type,

---

<div class="post-metadata">

**Author:** ![mnemnion](https://ziggit.dev/user_avatar/ziggit.dev/mnemnion/32/2478_2.png) [@mnemnion](https://ziggit.dev/u/mnemnion)\
**Post date:** [May 26, 2024, 7:37pm UTC](https://ziggit.dev/t/result-location-semantics/3579/18 "2024-05-26T19:37:19Z")

</div>

> [@nyc](#):
>
> @TypeOf’s function definition is @TypeOf(…) because you can give it any number of argument. There’s a few others too I think.

The exceptions are `@TypeOf` and `@compileLog`. These are actually macros, by any reasonable definition. The language could add the only runtime function which takes either one or two arguments, just to have a variadic `@intCast`, but I don’t see why it should. `@downCast(T, v)` would do the job just fine, and the `@as(T, @intCast(v))` pattern is common enough, and awkward enough, to justify the inclusion.

We’ll have to agree to disagree about whether RLS should see through arbitrarily complex arithmetic to infer the result type. I say that would lead to code which is easy to get wrong, and hard to understand when read. Zig doesn’t do implicit conversion, and having to know the type of `x` in `x + @intCast(y)` to deduce the conversion type is what I consider implicit.

---

<div class="post-metadata">

**Author:** ![nyc](https://ziggit.dev/user_avatar/ziggit.dev/nyc/32/1167_2.png) [@nyc](https://ziggit.dev/u/nyc)\
**Post date:** [May 26, 2024, 7:50pm UTC](https://ziggit.dev/t/result-location-semantics/3579/19 "2024-05-26T19:50:55Z")

</div>

> [@mnemnion](#):
>
> say that would lead to code which is easy to get wrong, and hard to understand when read

for lossless conversions, that shouldnt be an issue.

you would need an int versions and ptr versions I think of the two type. I think those are my most common. (and a two are intfromenum since those can get really bad `@as(T, @intCast(@intFromEnum(E)))`

I dont think that RLS has been proven itself in my mind yet. I definitely like it less than I thought I would.

---

<div class="post-metadata">

**Author:** ![msw](https://ziggit.dev/user_avatar/ziggit.dev/msw/32/2986_2.png) [@msw](https://ziggit.dev/u/msw)\
**Post date:** [June 4, 2024, 12:27pm UTC](https://ziggit.dev/t/result-location-semantics/3579/20 "2024-06-04T12:27:26Z")

</div>

I find it funny how “peer type resolution” in, say, addition, can complain that the types aren’t the same, but I need to spell them out explicitly _again_.

If the compiler knows due to PTR that the type is wrong, shouldn’t that locally be the RLS for this position as well? (i.e., shouldn’t it be enough to say `const z: i32 = x + @intCast(y)` in `pub noinline fn f()` as written by nyc?).

I’m doing a lot of math involving `f32` and `[iu]32` (different sources, different sinks) and I find it unnesserily verbose to keep writing the types. Then one refactors something and there’s a lot of churn…

Then again, a `comptime_int` will easily become a runtime float with PTR, so to some extent the logic seems to be already there.

[Next page](https://ziggit.dev/t/result-location-semantics/3579.md?page=2)
