template ctor overload Segmentation fault

RazvanN razvan.nitu1305 at gmail.com
Tue Dec 14 12:04:36 UTC 2021


On Sunday, 12 December 2021 at 11:57:43 UTC, vit wrote:
> Hello, why does this code fail to compile?
>
> ```d
> struct Foo(T){
>     this(Rhs, this This)(scope Rhs rhs){
>     }
>
>     this(ref scope typeof(this) rhs){
>     }
> }
>
>
> struct Bar{
> 	Foo!int foo;
> }
>
> void main(){
> }
> ```
>
> error: Segmentation fault (core dumped)

The problem is that the compiler will try to generate an inout 
copy constructor for Bar that looks roughly like this:

```
this(ref scope inout(Bar) p) inout
{
     this.foo = p;
}
```

The idea behind this lowering is to try and call the copy 
constructor for Foo object if possible. One issue here is that 
copy constructors have the same symbol name as constructors 
(__ctor), so `this.foo = p` gets lowered to `foo.__ctor(p)`.
Since both the instance and the parameter are inout, the copy 
constructor of Foo cannot be called, so the templated constructor 
is called. After generating the template instance of the 
constructor, you end up with `this(scope inout(Foo)) inout` ; 
that is basically an rvalue constructor. This is not valid code; 
if you write:

```
struct Foo(T){
     //this(Rhs, this This)(scope Rhs rhs){}
     this(scope inout(Foo!int) rhs) inout {}

     this(ref scope typeof(this) rhs){
     }
}
```

You will get an error stating that you cannot define both an 
rvalue constructor and a copy constructor. However, since the 
constructor is templated it is impossible for the compiler to 
issue this error before actually instantiating the constructor. I 
see 2 possible fixes for this: (1) either we rename the copy 
constructor symbol to __cpCtor so that it does not clash with the 
normal constructor overload set or (2) when a templated 
constructor is instantiated, we can check whether it is an rvalue 
constructor and issue an error if a copy constructor exists.

When I implemented the copy constructor I thought that it would 
better to have the copy constructor on a different overload set 
than the normal constructors, however, Walter insisted that they 
have the same name. So, I guess (2) is the way to go.

Cheers,
RazvanN


More information about the Digitalmars-d-learn mailing list