April 29
https://issues.dlang.org/show_bug.cgi?id=24528

          Issue ID: 24528
           Summary: Add offending member to "no size because of forward
                    reference" error
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: johanengelen@weka.io

I don't have a testcase (I hit it on a complex codebase), but improvement is
needed for the "no size because of forward reference" error reported by
`AggregateDeclaration.determineSize`
(https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/aggregate.d#L237).

The error now reads:
`Error: struct `A` no size because of forward reference`
It is unclear what the forward reference is. Is there a forward reference
inside struct `A`? Is struct `A` referenced elsewhere (if yes, where?) which
constitutes the forward reference?

What helped me find the fwd reference quickly in the code, is hacking the compiler to add extra diagnostics. All paths that lead to the error (`goto LFail` or the "fallthrough" before `Lfail`) should store which struct member field is causing trouble, such that it can be reported upon error.

1. `determineSize` https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/aggregate.d#L218 2. `determineFields` https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/aggregate.d#L224 3. `finalizeSize` https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/aggregate.d#L226

In my case, I added extra error output inside `finalizeSize` (https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/dstruct.d#L297) which got me to the actual code problem.

Perhaps change this code:
```
        for (size_t i = 0; i < members.length; i++)
        {
            Dsymbol s = (*members)[i];
            s.setFieldOffset(this, &fieldState, isunion);
        }
        if (type.ty == Terror)
        {
            .error(loc, "finalizeSize err");
            errors = true;
            return;
        }
```

to this:

```
        for (size_t i = 0; i < members.length; i++)
        {
            Dsymbol s = (*members)[i];
            s.setFieldOffset(this, &fieldState, isunion);
            if (type.ty == Terror)
            {
                error(loc, "error on member `%s`", s.toPrettyChars);
                errors = true;
                return;
            }
        }
```

--