﻿id	summary	reporter	owner	description	type	status	priority	component	version	resolution	keywords	cc
186	Cannot add extra assertion on a constructor	mlbrooks		"Conflicts or confusion happen when trying to declare a custom constructor, which intends to replace an autogen constructor, if the custom constructor is adding assertions beyond those of the struct declaration (which is the set of assertions that applies to visible autogen constructors).  The replacement happens only partially; two examples are detailed below.

A simple example has neither constructor being callable.

{{{
struct S {};

forall( | {void sayHi();} )
void ?{}( S & this ) {
    sayHi();
}

void sayHi() {
    printf(""hi\n"");
}

int main() {
    S s;
}
}}}

Expected, simple: compile success with output
{{{
hi
}}}

Actual, simple: compiler error
{{{
Unique best alternative includes deleted identifier in Generated Cast of:
  Application of
    Deleted Expression
      Variable Expression: ?{}: static inline function
      ... with parameters
        _dst: reference to instance of struct S with body 1
      ... returning nothing

      ... deleted by: ?{}: forall
        __anonymous0: data type
        ... with assertions
          sayHi: pointer to function
            accepting unspecified arguments
          ... returning nothing
}}}

Note that the error says the custom constructor is responsible for deleting the autogen constructor (which is correct), yet the call site is preferring the autogen constructor (which is incorrect).

A consequence of this first example is, when there is no generic type parameter on the structure, all constructors must use the same set of assertions.  This represents a limitation of the resource-management/traits system, in that a specialized resource acquisition strategy cannot be applied for a scenario indicated by the presence of a certain API.

A more elaborate example has the autogen constructor being called in spite of the same-signature custom constructor, which is confusing and hard to troubleshoot.

{{{
forall( dtype T ) {
    struct S {
        T * t;
    };

    forall( | {void sayHi();} )
    void ?{}( S(T) & this, T * t ) {
        sayHi();
        this.t = 0p;
    }
}

void sayHi() {
    printf(""hi\n"");
}

int main() {
    int x = 7;
    S(int) s = { & x };
    printf(""%s\n"", (s.t == 0p) ? ""null"" : ""not null"");
}
}}}

Expected, elaborate: compiler success with output
{{{
hi
null
}}}

Actual, elaborate: compiler success with output
{{{
not null
}}}

The actual-elaborate output is suggesting that the autogen 1-param constructor is being called.  Manual inspection of -CFA output corroborates.

In this revision of the elaborate case, the behaviour is reversed.  This does provide a workaround (for cases when the struct has generic parameters).  But note the extreme similarity of the two elaborate code listings: all our instincts about forall distribution are screaming that the two should be the same.

{{{
forall( dtype T ) {
    struct S {
        T * t;
    };
}

forall( dtype T | {void sayHi();} ) {
    void ?{}( S(T) & this, T * t ) {
        sayHi();
        this.t = 0p;
    }
}

void sayHi() {
    printf(""hi\n"");
}

int main() {
    int x = 7;
    S(int) s = { & x };
    printf(""%s\n"", (s.t == 0p) ? ""null"" : ""not null"");
}
}}}

Actual, elaborate revised: as expected elaborate
"	defect	new	major	cfa-cc	1.0			
