digitalmars.D.learn - Cast converts AA to rvalue?
- Johan (17/17) Aug 09 2022 Testcase:
- Steven Schveighoffer (9/23) Aug 09 2022 So what is happening is you are casting away shared on the expression
- Johan (14/26) Aug 10 2022 I think old compilers parsed it as `(cast()aa)[1]`, which works
Testcase:
```
shared int[int] aa;
void main () {
cast()aa[1] = 1;
}
```
Up to dlang 2.097, this program runs and works fine.
Since dlang 2.098, the program errors with:
`core.exception.RangeError /app/example.d(3): Range violation`
I think the 2.098+ behavior is correct, but I cannot find
anything about the change of this language behavior in the
release notes.
Please enlighten me,
Johan
related discussion:
https://forum.dlang.org/post/etxuhqzlkofitxswsxel forum.dlang.org
Aug 09 2022
On 8/9/22 7:02 PM, Johan wrote:
Testcase:
```
shared int[int] aa;
void main () {
cast()aa[1] = 1;
}
```
Up to dlang 2.097, this program runs and works fine.
Since dlang 2.098, the program errors with:
`core.exception.RangeError /app/example.d(3): Range violation`
I think the 2.098+ behavior is correct, but I cannot find anything about
the change of this language behavior in the release notes.
So what is happening is you are casting away shared on the expression
`aa[1]`. This expression by itself is an *access* of a value, not an
*assignment*. This is consistent for structs defining both opIndex and
opIndexAssign (the expression calls `opIndex`, not `opIndexAssign`), as
far back as I can test.
If you use `cast()(aa[1]) = 1`, it has a range error even on older versions.
That it ever worked is puzzling.
-Steve
Aug 09 2022
On Wednesday, 10 August 2022 at 00:28:53 UTC, Steven Schveighoffer wrote:On 8/9/22 7:02 PM, Johan wrote:I think old compilers parsed it as `(cast()aa)[1]`, which works on newer compilers too without range error. In my case, `aa` is also `immutable`. The only way I know how to make it work is now pretty ugly (casting away immutable should be ugly, so perhaps it's OK...): ``` shared immutable int[int] aa; void main () { // (cast()aa)[1] = 1; // works without immutable (*cast(int[int]*)(&aa))[1] = 1; } ```Testcase: ``` shared int[int] aa; void main () { cast()aa[1] = 1; } ```If you use `cast()(aa[1]) = 1`, it has a range error even on older versions. That it ever worked is puzzling.
Aug 10 2022
On 10.08.22 10:20, Johan wrote:
```
shared immutable int[int] aa;
void main () {
// (cast()aa)[1] = 1; // works without immutable
(*cast(int[int]*)(&aa))[1] = 1;
}
```
We have shared static constructors for that:
shared static this()
{
aa[1] = 1; /* no cast needed */
}
Aug 10 2022
On Wednesday, 10 August 2022 at 09:52:10 UTC, ag0aep6g wrote:On 10.08.22 10:20, Johan wrote:But our code is not a toy example ;-) (sorry for unnecessary snarky remark) ``` void f() { aa[1] = 1; // error } shared static this() { f(); } ``` I had considered it, but discarded it... `f` is also a template in our code. Your remark made me check again, and the call chain is short, perhaps I'll convert `f` to a template mixin... Unfortunately doesn't work: "immutable variable `aa` initialization is not allowed in nested function `f`". -Johan``` shared immutable int[int] aa; void main () { // (cast()aa)[1] = 1; // works without immutable (*cast(int[int]*)(&aa))[1] = 1; } ```We have shared static constructors for that: shared static this() { aa[1] = 1; /* no cast needed */ }
Aug 10 2022
On Wednesday, 10 August 2022 at 17:14:08 UTC, Johan wrote:
```
void f() {
aa[1] = 1; // error
}
shared static this()
{
f();
}
```
I had considered it, but discarded it... `f` is also a template
in our code. Your remark made me check again, and the call
chain is short, perhaps I'll convert `f` to a template mixin...
Unfortunately doesn't work: "immutable variable `aa`
initialization is not allowed in nested function `f`".
If you can build a mutable version of the array in a `pure`
function, you can do it like this:
```d
int[int] make_aa() pure
{
int[int] maa;
maa[1] = 1; /* or function calls, or whatever */
return maa;
}
immutable int[int] aa;
shared static this()
{
aa = make_aa();
}
```
If you can't do it in a `pure` function, you can do it with a
cast: `aa = cast(immutable) make_aa();`.
Casting from mutable to immutable is better, because it does not
have undefined behavior (as long as you don't use a mutable
reference later). Your casting away immutable and then mutating
does have undefined behavior.
Aug 10 2022








ag0aep6g <anonymous example.com>