Why this compilation error ?

259 views
Skip to first unread message

Christophe Meessen

unread,
Mar 16, 2025, 9:30:25 AMMar 16
to golang-nuts
Hello,

You'll find the minimal example code generating the compilation error
here: https://go.dev/play/p/Vb-dNr2DpzM

It is easy to get around it as the example shows. Why is the compiler
considering this as an error ?

--
Bien cordialement
Ch.Meessen

Jan Mercl

unread,
Mar 16, 2025, 9:33:54 AMMar 16
to Christophe Meessen, golang-nuts
On Sun, Mar 16, 2025 at 2:30 PM 'Christophe Meessen' via golang-nuts
<golan...@googlegroups.com> wrote:

> You'll find the minimal example code generating the compilation error
> here: https://go.dev/play/p/Vb-dNr2DpzM
>
> It is easy to get around it as the example shows. Why is the compiler
> considering this as an error ?

See https://go.dev/ref/spec#Composite_literals

""""
A parsing ambiguity arises when a composite literal using the TypeName
form of the LiteralType appears as an operand between the keyword and
the opening brace of the block of an "if", "for", or "switch"
statement, and the composite literal is not enclosed in parentheses,
square brackets, or curly braces. In this rare case, the opening brace
of the literal is erroneously parsed as the one introducing the block
of statements. To resolve the ambiguity, the composite literal must
appear within parentheses.
""""

tapi...@gmail.com

unread,
Mar 17, 2025, 4:44:42 AMMar 17
to golang-nuts
You can use *new(Version) instead of Version{} to avoid parsing ambiguity.

Jan Mercl

unread,
Mar 17, 2025, 4:49:51 AMMar 17
to tapi...@gmail.com, golang-nuts
On Mon, Mar 17, 2025 at 9:45 AM tapi...@gmail.com <tapi...@gmail.com> wrote:

> You can use *new(Version) instead of Version{} to avoid parsing ambiguity.

FTR: This would never pass my review.

tapi...@gmail.com

unread,
Mar 18, 2025, 12:03:41 AMMar 18
to golang-nuts
I prefer *new(T) over T{}, because not only the reason here, but also the former has a smaller inline cost.

Dan Kortschak

unread,
Mar 18, 2025, 2:39:19 AMMar 18
to golan...@googlegroups.com
On Mon, 2025-03-17 at 21:03 -0700, tapi...@gmail.com wrote:
> I prefer *new(T) over T{}, because not only the reason here, but also
> the former has a smaller inline cost.

What do you mean by "inline cost"?

https://godbolt.org/z/h8Krq7W8G

tapi...@gmail.com

unread,
Mar 18, 2025, 10:22:48 AMMar 18
to golang-nuts
Inline cost is estimated at compile time, not the real code.

But I sorry to say "*new(T) has a smaller inline cost than T{}". it is a little larger in fact.
The inline cost of new(T) is smaller than T{}. I got it mixed up. 

tapi...@gmail.com

unread,
Mar 18, 2025, 10:23:17 AMMar 18
to golang-nuts
s/code/cost

Davis Goodin

unread,
Mar 18, 2025, 12:38:50 PMMar 18
to golang-nuts
Inline cost is part of how Go decides what funcs to inline. There are some interesting patterns (maybe even idioms?) in Go that specifically try to inline a lot of code to prevent values from escaping to the heap when they don't have to. Concrete examples from -gcflags='-m -m':

./main.go:7:6: can inline fooCompositeLiteral with cost 3 as: func() { _ = Version{} }
./main.go:11:6: can inline fooCompositeLiteralP with cost 4 as: func() { _ = &Version{} }
./main.go:15:6: can inline fooNew with cost 4 as: func() { _ = *new(Version) }
./main.go:19:6: can inline fooNewP with cost 3 as: func() { _ = new(Version) }

In a tight spot, that 1 cost might make a drastic difference.

christoph...@gmail.com

unread,
Mar 18, 2025, 1:28:59 PMMar 18
to golang-nuts

I couldn't find a clear answer to my question. I didn't see what I was supposed to find in the reference manual.
On my side I understood that the {} caused an ambiguity with the { of the if clause. The ambiguity is removed by putting the expression in parenthesis.

if (v == Version{}) {. // <-- no more compiler error

I suppose there would be a similar problem with an if statement. Didn't check.

Davis Goodin

unread,
Mar 18, 2025, 2:20:57 PMMar 18
to golang-nuts
See the section wrapped in """ in Jan's reply. Quoted differently:

> A parsing ambiguity arises when a composite literal using the TypeName form of the LiteralType appears as an operand between the keyword and the opening brace of the block of an "if", "for", or "switch" statement, and the composite literal is not enclosed in parentheses, square brackets, or curly braces. In this rare case, the opening brace of the literal is erroneously parsed as the one introducing the block of statements. To resolve the ambiguity, the composite literal must appear within parentheses.
>
> if x == (T{a,b,c}[i]) { … }
> if (x == T{a,b,c}[i]) { … }
Reply all
Reply to author
Forward
0 new messages