Thread overview
Failure due to memcpy being called at compile time
Jun 13, 2022
JG
Jun 13, 2022
JG
Jun 13, 2022
JG
Jun 13, 2022
Paul Backus
Jun 14, 2022
JG
Jun 21, 2022
Paul Backus
Jun 21, 2022
JG
Jun 21, 2022
Paul Backus
June 13, 2022

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?

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");
}
June 13, 2022

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?

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

June 13, 2022

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?

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:

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");
}
June 13, 2022

On 6/13/22 4:09 PM, JG wrote:

>

Thanks. It seems to be something to do with the variadic template since this
works:

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

Given that it's inside moveEmplace, I'd suspect something deep in SumType.

-Steve

June 13, 2022

On Monday, 13 June 2022 at 20:25:00 UTC, Steven Schveighoffer wrote:

>

On 6/13/22 4:09 PM, JG wrote:

>

Thanks. It seems to be something to do with the variadic template since this
works:

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

Given that it's inside moveEmplace, I'd suspect something deep in SumType.

-Steve

Really strange. I can also work around it like this:

```d
auto parserOr(I,fs...)(I i) if(fs.length>=2) {
  auto cur = fs[0](i);
  if(cur.match!((ParseError e)=>false,_=>true)) { return cur; }
  static if(fs.length==2) { return fs[1](i); }
  else { return parserOr!(I,fs[1..$])(i); }
}
```
June 13, 2022

On Monday, 13 June 2022 at 19:48:06 UTC, 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?

Reduced further:

import std.sumtype;

struct Tuple
{
	void opAssign(Tuple rhs) {}
}

alias ParseErrorOr = SumType!Tuple;

auto parserOr() {
	ParseErrorOr cur;
	cur = ParseErrorOr(Tuple());
	return cur;
}

void main()
{
	enum a = parserOr();
}

The call to move is coming from SumType.opAssign:

https://github.com/dlang/phobos/blob/v2.100.0/std/sumtype.d#L681

I've filed a bugzilla issue for this here:

https://issues.dlang.org/show_bug.cgi?id=23182

June 14, 2022

On Monday, 13 June 2022 at 21:45:39 UTC, Paul Backus wrote:

>

On Monday, 13 June 2022 at 19:48:06 UTC, 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?

Reduced further:

import std.sumtype;

struct Tuple
{
	void opAssign(Tuple rhs) {}
}

alias ParseErrorOr = SumType!Tuple;

auto parserOr() {
	ParseErrorOr cur;
	cur = ParseErrorOr(Tuple());
	return cur;
}

void main()
{
	enum a = parserOr();
}

The call to move is coming from SumType.opAssign:

https://github.com/dlang/phobos/blob/v2.100.0/std/sumtype.d#L681

I've filed a bugzilla issue for this here:

https://issues.dlang.org/show_bug.cgi?id=23182

Thanks, for doing this.

June 21, 2022

On Tuesday, 14 June 2022 at 05:35:46 UTC, JG wrote:

>

On Monday, 13 June 2022 at 21:45:39 UTC, Paul Backus wrote:

>

The call to move is coming from SumType.opAssign:

https://github.com/dlang/phobos/blob/v2.100.0/std/sumtype.d#L681

I've filed a bugzilla issue for this here:

https://issues.dlang.org/show_bug.cgi?id=23182

Thanks, for doing this.

Update: a new release of the sumtype package on code.dlang.org is available that includes the fix for this bug.

std.sumtype will be fixed in the next Phobos release, 2.100.1.

June 21, 2022

On Tuesday, 21 June 2022 at 01:39:43 UTC, Paul Backus wrote:

>

On Tuesday, 14 June 2022 at 05:35:46 UTC, JG wrote:

>

On Monday, 13 June 2022 at 21:45:39 UTC, Paul Backus wrote:

>

The call to move is coming from SumType.opAssign:

https://github.com/dlang/phobos/blob/v2.100.0/std/sumtype.d#L681

I've filed a bugzilla issue for this here:

https://issues.dlang.org/show_bug.cgi?id=23182

Thanks, for doing this.

Update: a new release of the sumtype package on code.dlang.org is available that includes the fix for this bug.

std.sumtype will be fixed in the next Phobos release, 2.100.1.

That is great. Is this a work around the CFE bug?

June 21, 2022

On Tuesday, 21 June 2022 at 04:30:25 UTC, JG wrote:

>

On Tuesday, 21 June 2022 at 01:39:43 UTC, Paul Backus wrote:

>

Update: a new release of the sumtype package on code.dlang.org is available that includes the fix for this bug.

std.sumtype will be fixed in the next Phobos release, 2.100.1.

That is great. Is this a work around the CFE bug?

Yes, it's a workaround to avoid calling memcpy in CTFE.