Issue 24634 - Parse error initializing array from expression with StructInitializer
Summary: Parse error initializing array from expression with StructInitializer
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 normal
Assignee: No Owner
URL:
Keywords: pull
Depends on:
Blocks:
 
Reported: 2024-06-26 22:30 UTC by Tom Kral
Modified: 2024-06-29 15:32 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Tom Kral 2024-06-26 22:30:43 UTC
Compiling the following code fails with:

Error: found `}` when expecting `;` following expression

```
struct A { int val; }

enum A[2] as = [{0}, {1}].update;

auto update(A[] as) {
    foreach (ref a; as) a.val++;
    return as;
}
```

Interestingly, if I replace struct initializers with struct ctors, e.g.:

```
enum A[2] as = [A(0), A(1)].update;
```

the code compiles just fine.
Comment 1 basile-z 2024-06-27 12:33:36 UTC
That's not really a bug. The problem is that StructInitializer is not supported when the variable initializer is an AssignExpression. You can verify that in the specifications: https://dlang.org/spec/declaration.html#initialization:

```
auto A[1] as = [{0}]; 
```

takes the path of ArrayLiteral. ArrayLiteral supports StructInitializer.

```
auto A[1] as = [{0}].update(); 
```

takes the path of AssignExpression. AssignExpression dont support StructInitializer.

As a workaround you can decompose

```
auto A[1] as0 = [{0}]; 
auto A[1] as1 = [{0}].update(); 
```
Comment 2 basile-z 2024-06-27 12:34:28 UTC
Sorry I meant to write

```
auto A[1] as0 = [{0}]; 
auto A[1] as1 = as0.update(); 
```
Comment 3 Nick Treleaven 2024-06-27 13:26:44 UTC
> AssignExpression dont support StructInitializer

No - AssignExpression can be a PostfixExpression, which can have a PrimaryExpression on the left, which can be an ArrayLiteral, which can have a StructInitializer element.
Comment 4 Tom Kral 2024-06-27 17:36:00 UTC
(In reply to basile-z from comment #2)
> Sorry I meant to write
> 
> ```
> auto A[1] as0 = [{0}]; 
> auto A[1] as1 = as0.update(); 
> ```

Hmm, I find it rather surprising that StructInitializer would not work in this case. Is there a good reason for that?

Thanks for the workaround by the way, it did the trick.
Comment 5 Dlang Bot 2024-06-29 09:55:53 UTC
@ntrel created dlang/dlang.org pull request #3864 "[spec] Restore *ArrayInitializer*" fixing this issue:

- [spec] Restore *ArrayInitializer*
  
  It was merged with ArrayLiteral in #3215 (oops).
  
  Fixes Bugzilla 24634 - Parse error initializing array from expression with StructInitializer.
  
  Add examples.

https://github.com/dlang/dlang.org/pull/3864
Comment 6 Nick Treleaven 2024-06-29 10:01:39 UTC
basile-z is right that the compiler can't parse a struct initializer as part of an expression. The ArrayLiteral spec was wrong - the pull fixes that.

Tom Kral:
> I find it rather surprising that StructInitializer would not work in this case. Is there a good reason for that?

It is part of a function argument, which in turn is part of an expression initializer (because a function call is an expression). An expression cannot parse all initializers because some initializers (e.g. `{}` for struct) mean something else as an expression (a function literal). So initializers are not accepted inside an expression.
Comment 7 Dlang Bot 2024-06-29 15:32:25 UTC
dlang/dlang.org pull request #3864 "[spec] Restore *ArrayInitializer*" was merged into master:

- 4700925acae3df03c6e5399f81df47927240be6a by Nick Treleaven:
  [spec] Restore *ArrayInitializer*
  
  It was merged with ArrayLiteral in #3215 (oops).
  
  Fixes Bugzilla 24634 - Parse error initializing array from expression with StructInitializer.
  
  Add examples.

https://github.com/dlang/dlang.org/pull/3864