Skip to content

Go: a condition comparing against a struct literal generates if p == Point{1, 2} {, which is a Go syntax error #105

Description

@matt-edmondson

What's wrong

To match gofmt, GoGenerator.WriteCondition (Coder/Languages/GoGenerator.cs ~1597-1605) drops the outer parentheses of a BinaryExpression/UnaryExpression used as an if/for/switch clause. Go's grammar, however, has a composite-literal ambiguity: inside an if/for/switch header, TypeName{ is parsed as the start of the block. A composite literal that appears directly as an operand there must be parenthesised (Go spec: Composite literals, "parsing ambiguity"). The generator writes the struct construction bare.

Repro (reproduced with MSTest, output checked with go run)

AST: ReturnStatement(ConditionalExpression(BinaryExpression(VariableReference("p"), Equal, ConstructionExpression(Point){1, 2}), 1, 0)), with Point a two-field struct.

  • Generated: if p == Point{1, 2} {
  • go run: syntax error: unexpected }, expected := or = or comma
  • Expected: if p == (Point{1, 2}) {. Checked: this compiles and returns 1.

The same happens for an IfStatement/WhileStatement condition, and for the func() T { if … }() form that conditionals take in assignment/argument position, since all of them go through WriteCondition.

Suggested fix

In WriteCondition, when either direct operand (or a call receiver at the top level of the condition) is a ConstructionExpression that Go spells with braces (a struct literal: more than one argument or any MemberInitialiser), parenthesise that operand. Alternatively, keep the outer parentheses whenever the condition contains such an operand. Add a Go compile test for a struct-equality condition.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingreadyFully specified; implement as written

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions