On Monday, 13 June 2022 at 19:59:16 UTC, Steven Schveighoffer
wrote:
On 6/13/22 3:48 PM, JG wrote:
Hi,
I reduced my code to the following. Could anyone help me to
discover why the line marked with //THIS LINE
causes memcpy to be called, and how can I avoid this?
```d
import std;
struct ParseError { string msg; }
alias ParseErrorOr(T) = SumType!(ParseError,T);
auto parseErrorOr(T)(T x) { return ParseErrorOr!T(x); }
auto parserOr(I,fs...)(I i) {
alias RetType = typeof(fs[0](I.init));
auto cur = RetType(ParseError.init);
foreach(f;fs) {
if(cur.match!((ParseError e)=>false,_=>true)) { return
cur; }
cur = f(i); //THIS LINE
}
return cur;
}
auto parseNothing(I)(I i) {
return parseErrorOr(tuple(i[0..0],i));
}
void main()
{
enum a =
parserOr!(string,parseNothing!string,parseNothing!string)("hello");
}
```
Happens in `moveEmplaceImpl` in `core.lifetime`. Somebody is
calling that.
https://github.com/dlang/druntime/blob/v2.099.1/src/core/lifetime.d#L2192
No stack trace though, that would actually be nice to have in
the CTFE interpreter.
I imagine if you solved that call, you would get out to a place
where it tries to cast to the actual type and fail there
instead.
-Steve
Thanks. It seems to be something to do with the variadic template
since this
works:
```d
import std;
struct ParseError { string msg; }
alias ParseErrorOr(T) = SumType!(ParseError,T);
auto parseErrorOr(T)(T x) { return ParseErrorOr!T(x); }
auto parserOr(I,alias f, alias g)(I i) {
auto cur = f(i);
if(cur.match!((ParseError e)=>false,_=>true)) { return cur; }
return g(i);
}
auto parseNothing(I)(I i) {
return parseErrorOr(tuple(i[0..0],i));
}
void main()
{
enum a =
parserOr!(string,parseNothing!string,parseNothing!string)("hello");
}
```