你使用的Go版本是什么( go version
)?
$ go version
go version go1.13.7 linux/amd64
这个问题在最新版本的发布中是否重现?
是的。
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/icza/.cache/go-build"
GOENV="/home/icza/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY="xxx"
GONOSUMDB="xxx"
GOOS="linux"
GOPATH="/home/icza/gows"
GOPRIVATE="xxx"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build104015454=/tmp/go-build -gno-record-gcc-switches"
你做了什么?
创建一个有效的 .go
源文件,该文件具有超过 1048574
行( 0xFFFFF
)。并在末尾添加一些“垃圾”以使其无效,导致编译失败。尝试构建它( go build big.go
)或运行它( go run big.go
),go工具检测到错误并显示错误消息,其中行号被错误地截断,例如:
./big.go:1048574:2: syntax error: unexpected invalid after top level declaration
这是一个简单的Go应用程序,它创建了一个 big.go
文件,该文件大约有两倍多的行数(它有一个原始字符串字面量,其中包含2*0xFFFFF个空行):
package main
import (
"bytes"
"io/ioutil"
"strings"
)
func main() {
src := &bytes.Buffer{}
src.WriteString(`package main
func main() { println(len(s)) }
const s=`)
src.WriteString("`")
src.WriteString(strings.Repeat("\n", 2*0xFFFFF))
src.WriteString("`")
// This is the garbage to make compilation fail:
src.WriteString("invalid")
if err := ioutil.WriteFile("big.go", src.Bytes(), 0666); err != nil {
panic(err)
}
}
如果我们减少生成的行数,例如:
src.WriteString(strings.Repeat("\n", 10_000))
我们会得到正确的行号( 10003
):
./big.go:10003:2: syntax error: unexpected invalid after top level declaration
你期望看到什么?
我期望在检测到错误的正确位置打印出正确的行号( 2*0xFFFFFF+3 = 2097153
):
./big.go:2097153:2: syntax error: unexpected invalid after top level declaration
你看到了什么?
显示的错误行号被错误地截断为 1048574
:
./big.go:1048574:2: syntax error: unexpected invalid after top level declaration
**注意:**这个问题在StackOverflow上报告: https://stackoverflow.com/questions/59951140/go-compiler-error-line-number-is-incorrect
3条答案
按热度按时间nnt7mjpx1#
我认为限制行号是可以的,但我们不应该报告错误的行号。我们应该说我们不知道。
(我认为没有必要强迫编译器使用更多的内存,以便为每个人的编译速度变慢,从而为非常大的文件提供更好的错误信息。这样的文件通常是机器生成的,因此要么没有错误,要么有很多错误。)
ffscu2ro2#
我将更改问题标题以符合@ianlancetaylor提到的建议。感谢您报告此问题。
fzwojiic3#
嘿,我做了一些调查,如果大家同意的话,我打算创建一个PR。
1048574 == 1 << 20 - 2
的限制来自这里我做了以下更改
并使用
./make.bash
重新编译了工具链。结果是,在我的Go 1.13中,这个问题仍然存在。
通过上述更改和重新编译的工具链,正确的错误行被报告。
makeLico
函数强制执行这个限制,它在MakePos中被使用。p.pos()
。这个
p.pos()
方法使用了 posAt,它使用了原始的 MakePos 函数。抱歉写了这么多冗长的回答,但我认为这概述了发生错误的途径和原因。
我喜欢Ian关于 不改变上限 的建议,但当报告的行达到这个上限时打印另一个消息。
我觉得这可能是
errorAt
或syntaxErrorAt
中的一个小改动(?),在返回之前进行简单的检查。如果位置等于限制,它将返回不同的消息。我会想出一个合适的建议并回到这个帖子。