Thread overview
Force lvalue (`cast(ref)`)
Jan 22
IchorDev
Jan 22
Juraj
January 22

Sometimes you want an rvalue to bind to ref, but the compiler can’t be sure the reference isn’t escaped. But if you know that the reference won’t be escaped, or you don’t care if your code is safe at all, you can use cast(ref) to forcibly turn an rvalue into an lvalue:

ref x = cast(ref)10;
x++; //10 exists for the duration of this function. If this function returns x by reference, it is undefined behaviour.
auto y = returnPassedRef(cast(ref)24);
y++; //24 exists for the duration of the function it was created in, so `returnPassedRef` safely returned it. If this function returns the reference however, it is undefined behaviour.

The cast is @system . If the lvalue reference is escaped, it is undefined behaviour.
Passing a newly made lvalue into return ref parameters should probably issue a warning.

This feature is useful in writing low-level code where safety is manually verified, especially when interfacing with C++ libraries.

Possible alternative: the hideous __lvalue. However, __rvalue is dissimilar in that it is not @system and does not produce undefined behaviour, whereas casts are often @system , so perhaps the dissimilar syntax is a good reflection of the differences between the two.

January 22
Why can we not make this "just work" without extra syntax?

I.e.

```d
void func(ref int);
func(2);
```

January 22

On Wednesday, 22 January 2025 at 09:02:14 UTC, Richard (Rikki) Andrew Cattermole wrote:

>

Why can we not make this "just work" without extra syntax?

I.e.

void func(ref int);
func(2);

Because there is the curse of preview switches ...
https://github.com/dlang/dmd/pull/17068

February 12

On Wednesday, 22 January 2025 at 08:58:56 UTC, IchorDev wrote:

>

[...]

Doesn't -preview=rvaluerefparam do this already? Or am I misunderstanding?

February 13

On Wednesday, 12 February 2025 at 09:36:15 UTC, Atila Neves wrote:

>

On Wednesday, 22 January 2025 at 08:58:56 UTC, IchorDev wrote:

>

[...]

Doesn't -preview=rvaluerefparam do this already? Or am I misunderstanding?

Yes, it does implicitly if it has to.

// requires -preview=rvaluerefparam
void f(ref int x) { }

f(10); // materializes a local variable, assigns 10, passes it to `f`
// with and without -preview=rvaluerefparam
void f(ref int x) { }
void f(int x) { }

f(10); // simply calls `f(int)`

I guess what the cast(ref) could do is this:

// with and without -preview=rvaluerefparam
void f(ref int x) { }
void f(int x) { }

f(cast(ref)10); // NEW: forces materializing a local variable, calls `f(ref int)`

I can’t imagine a use case, but lack of imagination is hardly an argument.

February 17

On Thursday, 13 February 2025 at 22:41:21 UTC, Quirin Schroll wrote:

>

On Wednesday, 12 February 2025 at 09:36:15 UTC, Atila Neves wrote:

>

[...]

Yes, it does implicitly if it has to.

// requires -preview=rvaluerefparam
void f(ref int x) { }

f(10); // materializes a local variable, assigns 10, passes it to `f`
// with and without -preview=rvaluerefparam
void f(ref int x) { }
void f(int x) { }

f(10); // simply calls `f(int)`

I guess what the cast(ref) could do is this:

// with and without -preview=rvaluerefparam
void f(ref int x) { }
void f(int x) { }

f(cast(ref)10); // NEW: forces materializing a local variable, calls `f(ref int)`

I can’t imagine a use case, but lack of imagination is hardly an argument.

I think lack of imagination when it comes to a use case is definitely an argument in favour of not adding a feature.

February 18
On 2/17/2025 1:05 AM, Atila Neves wrote:
> I think lack of imagination when it comes to a use case is definitely an argument in favour of not adding a feature.

I agree. A new feature needs a strong use case. "Why" is an argument, "Why not" is not.