[Issue 23305] New: Tuple.expand generates garbage values when passed to multiple lazy parameters
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Thu Aug 25 23:23:34 UTC 2022
https://issues.dlang.org/show_bug.cgi?id=23305
Issue ID: 23305
Summary: Tuple.expand generates garbage values when passed to
multiple lazy parameters
Product: D
Version: D2
Hardware: x86_64
OS: Linux
Status: NEW
Severity: normal
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: krzysztof.jajesnica at student.put.poznan.pl
import std.stdio;
import std.typecons;
auto foo(lazy int a, lazy int b, lazy int c, lazy int d) {
return tuple(d, c, b, a);
}
void main() {
auto r = foo(tuple(3,4,5,6).expand);
writeln(r);
}
This code prints "Tuple!(int,int,int,int)(0, 0, <random garbage>, 3)" on my
machine (DMD 2.100.0) and gives similar results on run.dlang.io (DMD 2.099.1).
The bug only occurs if Tuple is obtained directly from a function call - using
a Tuple stored in a variable works fine:
// this works
auto t = tuple(3,4,5,6);
auto r = foo(t.expand);
The bug also occurs with any struct/class declaring multiple fields using an
AliasSeq of types, not just std.typecons.Tuple:
// also affected
struct vec2 {
AliasSeq!(float,float) expand;
}
Looking at output of -vcg-ast it seems that when a Tuple is obtained directly
from a function call and .expand is passed to multiple lazy parameters, the
Tuple is put in a local variable inside the body of the delegate generated for
the first parameter, and the other delegates reuse the same variable. I'm
assuming this causes the other delegates to read whatever is in the same
location on the stack, hence semi-random garbage.
void main()
{
Tuple!(int, int, int, int) r = foo(
delegate int() pure nothrow @nogc @safe =>
(Tuple!(int, int, int, int) __tup82 = tuple(3, 4, 5, 6);) ,
__tup82.__expand_field_0,
delegate int() pure nothrow @nogc @safe => __tup82.__expand_field_1,
delegate int() pure nothrow @nogc @safe => __tup82.__expand_field_2,
delegate int() pure nothrow @nogc @safe => __tup82.__expand_field_3
);
writeln(r);
return 0;
}
For reference, LDC (1.30.0) refuses to compile foo(tuple(3,4,5,6).expand) and
gives the following error message:
app.d(9): Error: function `app.main.__dgliteral3` cannot access frame of
function `app.main.__dgliteral2`
app.d(9): Error: function `app.main.__dgliteral4` cannot access frame of
function `app.main.__dgliteral2`
app.d(9): Error: function `app.main.__dgliteral5` cannot access frame of
function `app.main.__dgliteral2`
GDC (12.1.1) also gives a similar error message.
--
More information about the Digitalmars-d-bugs
mailing list