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");
}
```

Reply via email to