Description
What version of Go are you using (go version
)?
8db1310 (tip, as of time of writing)
What did you do?
Here is an example reproducer: https://go.dev/play/p/sphL42iaX_a
I think it's a pretty obscure issue which requires a few things:
- the SourcePos mode enabled
- one or more
// +build
constraints, and no//go:build
comments - a change in the AST before the first
//+build
comment which offsets position such that the printer has to emit a//line
directive
As far as I can tell, here's what's going wrong:
- the call to
printer.*Config.Fprint
will fully print the given node (a File) and then call fixGoBuildLines to consolidate build directives and translate "plus builds" to the current//go:build
format - when printing comments, build constraints are special-cased: the current position of the writer is recorded to
p.plusBuild
, then the comment is written withp.writeString
- writeString checks if
SourcePos
is enabled and, if necessary, emits a line directive before writing its arg string to the output buffer
After printing, fixGoBuildLines turns //+build
comments into //go:build
by iterating the positions in p.plusBuild
and parsing the constraints at each:
for _, pos := range p.plusBuild {
y, err := constraint.Parse(p.commentTextAt(pos))
if err != nil {
x = nil
break
}
...
Because of SourcePos, the offsets recorded to p.plusBuild
can incorrectly point to a //line
comment, rather than a valid build constraint, so parsing fails, the loop exits, and subsequent plusBuild lines are ignored and the inserted block will be incomplete/incorrect.
What did you expect to see?
//+build
constraints should have been preserved and/or translated to//go:build
- I'm not sure if there's any value in a line directive on the build constraint comment -- perhaps that can be omitted.
What did you see instead?
In the reproducer, one of the build constraints is omitted and a seemingly unnecessary line directive is printed ts the top of the file.