Skip to content

go/ast: add BasicLit.ValueEnd field #76031

@adonovan

Description

@adonovan

Background: The BasicLit.End method computes the end position of a literal by adding its start position to the length of the BasicLit.Value string, which is assumed to be the complete raw text of the literal. However, for multiline raw string literals, the spec requires that carriage returns (as used in text files on Windows) are discarded, and this process occurs in the scanner, so the Value string in the syntax tree is shorter than the actual string, causing the End position to be computed incorrectly.

Proposal: We propose to record the actual end position of the token in a new field, BasicLit.ValueEnd.

	package ast // "go/ast"

	type BasicLit struct {
-		ValuePos token.Pos   // literal position
+		ValuePos, ValueEnd token.Pos   // literal position
		Kind     token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
		Value    string      // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`
	}

The implementation is trivial. The only real downside is that the new field pushes the size of the struct up from 4 words to 5, and its size class from 4 words to 6 words. BasicLits are very numerous, about 10% of all tokens according to the nodecount command, so adding this field may cause ASTs to increase space usage by about 2%.

Relatively few programs use the parser and are long running (and therefore care about memory pressure and GC costs). Gopls is arguably the most important among them. We gopls maintainers are willing to pay the memory price for the AST to record the input in greater fidelity, not just as it relates to this issue, but in a number of other ways as well. The way we see it is that there will be no go/ast v2 since it defines the entire Go tooling ecosystem, so we need to make incremental improvements. Computers have also gotten bigger and faster since go/ast was designed.

cc: @griesemer @findleyr

Metadata

Metadata

Assignees

Labels

LibraryProposalIssues describing a requested change to the Go standard library or x/ libraries, but not to a toolProposalProposal-Accepted

Type

No type

Projects

Status

Accepted

Relationships

None yet

Development

No branches or pull requests

Issue actions